@semacode/cli 1.3.2 → 1.3.5
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 +2 -2
- package/dist/index.js +33 -27
- package/package.json +21 -33
- package/semacode-cli-1.3.1.tgz +0 -0
- package/src/cpp-symbols.ts +82 -0
- package/src/dotnet-http.ts +355 -0
- package/src/drift.ts +2455 -0
- package/src/go-http.ts +118 -0
- package/src/importador.ts +3448 -0
- package/src/index.ts +4476 -0
- package/src/java-http.ts +247 -0
- package/src/projeto.ts +810 -0
- package/src/python-http.ts +258 -0
- package/src/rust-http.ts +125 -0
- package/src/tipos.ts +22 -0
- package/src/typescript-http.ts +1076 -0
- package/tsconfig.json +20 -0
- package/AGENTS.md +0 -272
- package/LICENSE +0 -22
- package/SEMA_BRIEF.curto.txt +0 -9
- package/SEMA_BRIEF.md +0 -49
- package/SEMA_BRIEF.micro.txt +0 -7
- package/SEMA_INDEX.json +0 -546
- package/dist/cpp-symbols.d.ts +0 -10
- package/dist/cpp-symbols.js.map +0 -1
- package/dist/dotnet-http.d.ts +0 -23
- package/dist/dotnet-http.js.map +0 -1
- package/dist/drift.d.ts +0 -118
- package/dist/drift.js.map +0 -1
- package/dist/go-http.d.ts +0 -23
- package/dist/go-http.js.map +0 -1
- package/dist/importador.d.ts +0 -29
- package/dist/importador.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/java-http.d.ts +0 -23
- package/dist/java-http.js.map +0 -1
- package/dist/lua-symbols.d.ts +0 -8
- package/dist/lua-symbols.js.map +0 -1
- package/dist/projeto.d.ts +0 -48
- package/dist/projeto.js.map +0 -1
- package/dist/python-http.d.ts +0 -23
- package/dist/python-http.js.map +0 -1
- package/dist/rust-http.d.ts +0 -23
- package/dist/rust-http.js.map +0 -1
- package/dist/tipos.d.ts +0 -3
- package/dist/tipos.js.map +0 -1
- package/dist/typescript-http.d.ts +0 -35
- package/dist/typescript-http.js.map +0 -1
- package/docs/AGENT_STARTER.md +0 -102
- package/docs/como-ensinar-a-sema-para-ia.md +0 -149
- package/docs/fluxo-pratico-ia-sema.md +0 -177
- package/docs/instalacao-e-primeiro-uso.md +0 -196
- package/docs/integracao-com-ia.md +0 -228
- package/docs/pagamento-ponta-a-ponta.md +0 -155
- package/docs/prompt-base-ia-sema.md +0 -104
- package/docs/sintaxe.md +0 -361
- package/exemplos/agendamento.sema +0 -106
- package/exemplos/assinatura.sema +0 -136
- package/exemplos/auditoria.sema +0 -88
- package/exemplos/autenticacao.sema +0 -125
- package/exemplos/automacao.sema +0 -107
- package/exemplos/cadastro_usuario.sema +0 -54
- package/exemplos/calculadora.sema +0 -78
- package/exemplos/crud_simples.sema +0 -89
- package/exemplos/estoque.sema +0 -126
- package/exemplos/exportacao.sema +0 -94
- package/exemplos/fila.sema +0 -131
- package/exemplos/integracao_externa.sema +0 -94
- package/exemplos/multi_tenant.sema +0 -140
- package/exemplos/notificacao.sema +0 -98
- package/exemplos/operacao_estrategia.sema +0 -402
- package/exemplos/pagamento.sema +0 -222
- package/exemplos/pagamento_dominio.sema +0 -35
- package/exemplos/pedido.sema +0 -119
- package/exemplos/permissao.sema +0 -121
- package/exemplos/relatorio.sema +0 -93
- package/exemplos/testes_embutidos.sema +0 -45
- package/exemplos/tratamento_erro.sema +0 -157
- package/exemplos/upload_arquivo.sema +0 -93
- package/exemplos/webhook.sema +0 -96
- package/llms-full.txt +0 -34
- package/llms.txt +0 -17
- package/node_modules/@sema/gerador-css/dist/index.d.ts +0 -3
- package/node_modules/@sema/gerador-css/dist/index.js +0 -592
- package/node_modules/@sema/gerador-css/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-css/package.json +0 -7
- package/node_modules/@sema/gerador-dart/dist/index.d.ts +0 -3
- package/node_modules/@sema/gerador-dart/dist/index.js +0 -44
- package/node_modules/@sema/gerador-dart/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-dart/package.json +0 -7
- package/node_modules/@sema/gerador-html/dist/index.d.ts +0 -3
- package/node_modules/@sema/gerador-html/dist/index.js +0 -163
- package/node_modules/@sema/gerador-html/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-html/package.json +0 -7
- package/node_modules/@sema/gerador-javascript/dist/index.d.ts +0 -3
- package/node_modules/@sema/gerador-javascript/dist/index.js +0 -421
- package/node_modules/@sema/gerador-javascript/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-javascript/package.json +0 -7
- package/node_modules/@sema/gerador-lua/dist/index.d.ts +0 -3
- package/node_modules/@sema/gerador-lua/dist/index.js +0 -328
- package/node_modules/@sema/gerador-lua/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-lua/package.json +0 -7
- package/node_modules/@sema/gerador-python/dist/index.d.ts +0 -6
- package/node_modules/@sema/gerador-python/dist/index.js +0 -628
- package/node_modules/@sema/gerador-python/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-python/package.json +0 -7
- package/node_modules/@sema/gerador-typescript/dist/index.d.ts +0 -6
- package/node_modules/@sema/gerador-typescript/dist/index.js +0 -656
- package/node_modules/@sema/gerador-typescript/dist/index.js.map +0 -1
- package/node_modules/@sema/gerador-typescript/package.json +0 -7
- package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +0 -122
- package/node_modules/@sema/nucleo/dist/ast/tipos.js +0 -2
- package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.d.ts +0 -21
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.js +0 -12
- package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/formatador/index.d.ts +0 -9
- package/node_modules/@sema/nucleo/dist/formatador/index.js +0 -445
- package/node_modules/@sema/nucleo/dist/formatador/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/index.d.ts +0 -34
- package/node_modules/@sema/nucleo/dist/index.js +0 -95
- package/node_modules/@sema/nucleo/dist/index.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.d.ts +0 -5
- package/node_modules/@sema/nucleo/dist/ir/conversor.js +0 -781
- package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +0 -285
- package/node_modules/@sema/nucleo/dist/ir/modelos.js +0 -2
- package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/lexer/lexer.d.ts +0 -7
- package/node_modules/@sema/nucleo/dist/lexer/lexer.js +0 -122
- package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/lexer/tokens.d.ts +0 -8
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js +0 -46
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.d.ts +0 -9
- package/node_modules/@sema/nucleo/dist/parser/parser.js +0 -656
- package/node_modules/@sema/nucleo/dist/parser/parser.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +0 -57
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js +0 -1497
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +0 -104
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +0 -445
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.d.ts +0 -91
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.js +0 -258
- package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +0 -1
- package/node_modules/@sema/nucleo/dist/util/arquivos.d.ts +0 -2
- package/node_modules/@sema/nucleo/dist/util/arquivos.js +0 -25
- package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +0 -1
- package/node_modules/@sema/nucleo/package.json +0 -7
- package/node_modules/@sema/padroes/dist/index.d.ts +0 -23
- package/node_modules/@sema/padroes/dist/index.js +0 -210
- package/node_modules/@sema/padroes/dist/index.js.map +0 -1
- package/node_modules/@sema/padroes/package.json +0 -7
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ sema --help
|
|
|
36
36
|
## Instalacao via tarball da release
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
npm install -g ./
|
|
39
|
+
npm install -g ./{{TGZ_ARQUIVO}}
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Ou direto da GitHub Release:
|
|
@@ -55,7 +55,7 @@ npx sema --help
|
|
|
55
55
|
Ou, se voce estiver testando um tarball local:
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
npm install ./
|
|
58
|
+
npm install ./{{TGZ_ARQUIVO}}
|
|
59
59
|
npx sema --help
|
|
60
60
|
```
|
|
61
61
|
|
package/dist/index.js
CHANGED
|
@@ -60,8 +60,8 @@ Comandos essenciais:
|
|
|
60
60
|
- validacao: \`sema validar <arquivo.sema> --json\`
|
|
61
61
|
- diagnosticos: \`sema diagnosticos <arquivo.sema> --json\`
|
|
62
62
|
- formatacao: \`sema formatar <arquivo.sema>\`
|
|
63
|
-
- importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
|
|
64
|
-
- geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>\`
|
|
63
|
+
- importacao assistida de legado: \`sema importar <nestjs|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|typescript|python|dart> <diretorio> --saida <diretorio>\`
|
|
64
|
+
- geracao de codigo: \`sema compilar <arquivo-ou-pasta> --alvo <typescript|python|dart|lua> --saida <diretorio>\`
|
|
65
65
|
- verificacao final: \`sema verificar <arquivo-ou-pasta> [--json]\`
|
|
66
66
|
|
|
67
67
|
Antes de editar:
|
|
@@ -100,24 +100,24 @@ Superficies que a IA deve enxergar como first-class:
|
|
|
100
100
|
|
|
101
101
|
Nao improvise quando faltar contexto.
|
|
102
102
|
`;
|
|
103
|
-
const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para operacao por IA.
|
|
104
|
-
|
|
105
|
-
Trate a Sema como camada semantica e linguagem de especificacao executavel feita para IA, nao para leitura humana confortavel. Nao invente sintaxe, palavras-chave ou blocos fora da gramatica e dos exemplos oficiais.
|
|
106
|
-
|
|
107
|
-
Fontes de verdade, em ordem:
|
|
108
|
-
1. se o projeto expuser \`SEMA_CONTEXT.md\`, comece por ele
|
|
109
|
-
2. \`SEMA_BRIEF.md\`
|
|
110
|
-
3. \`SEMA_INDEX.json\`
|
|
111
|
-
4. README do projeto
|
|
112
|
-
5. gramatica e documentacao de sintaxe da Sema
|
|
113
|
-
6. especificacao semantica da linguagem
|
|
114
|
-
7. exemplos oficiais, com prioridade para o vertical de pagamento
|
|
115
|
-
8. \`sema resumo\` e \`briefing.min.json\` quando a IA for pequena
|
|
116
|
-
9. AST, IR e diagnosticos exportados pela CLI em JSON quando a capacidade aguentar
|
|
117
|
-
|
|
118
|
-
Regras de operacao:
|
|
119
|
-
- preserve o significado semantico
|
|
120
|
-
- use o formatador oficial da Sema como fonte unica de estilo
|
|
103
|
+
const PROMPT_BASE_IA = `Voce esta trabalhando com Sema, um Protocolo de Governanca de Intencao orientado a contrato, desenhado para operacao por IA.
|
|
104
|
+
|
|
105
|
+
Trate a Sema como camada semantica e linguagem de especificacao executavel feita para IA, nao para leitura humana confortavel. Nao invente sintaxe, palavras-chave ou blocos fora da gramatica e dos exemplos oficiais.
|
|
106
|
+
|
|
107
|
+
Fontes de verdade, em ordem:
|
|
108
|
+
1. se o projeto expuser \`SEMA_CONTEXT.md\`, comece por ele
|
|
109
|
+
2. \`SEMA_BRIEF.md\`
|
|
110
|
+
3. \`SEMA_INDEX.json\`
|
|
111
|
+
4. README do projeto
|
|
112
|
+
5. gramatica e documentacao de sintaxe da Sema
|
|
113
|
+
6. especificacao semantica da linguagem
|
|
114
|
+
7. exemplos oficiais, com prioridade para o vertical de pagamento
|
|
115
|
+
8. \`sema resumo\` e \`briefing.min.json\` quando a IA for pequena
|
|
116
|
+
9. AST, IR e diagnosticos exportados pela CLI em JSON quando a capacidade aguentar
|
|
117
|
+
|
|
118
|
+
Regras de operacao:
|
|
119
|
+
- preserve o significado semantico
|
|
120
|
+
- use o formatador oficial da Sema como fonte unica de estilo
|
|
121
121
|
- use diagnosticos estruturados como contrato de correcao
|
|
122
122
|
- use a IR como fonte de verdade semantica quando houver duvida
|
|
123
123
|
- nao conclua uma alteracao sem validar e verificar o modulo
|
|
@@ -432,29 +432,35 @@ async function escreverArquivos(base, arquivos) {
|
|
|
432
432
|
}
|
|
433
433
|
}
|
|
434
434
|
function obterOpcao(args, nome, padrao) {
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
435
|
+
const nomes = [nome, ...Object.entries(ALIAS_OPCOES).filter(([, v]) => v === nome).map(([k]) => k)];
|
|
436
|
+
for (const n of nomes) {
|
|
437
|
+
const indice = args.findIndex((arg) => arg === n);
|
|
438
|
+
if (indice !== -1)
|
|
439
|
+
return args[indice + 1] ?? padrao;
|
|
438
440
|
}
|
|
439
|
-
return
|
|
441
|
+
return padrao;
|
|
440
442
|
}
|
|
441
443
|
function possuiFlag(args, nome) {
|
|
442
444
|
return args.includes(nome);
|
|
443
445
|
}
|
|
444
446
|
const OPCOES_COM_VALOR = new Set([
|
|
445
447
|
"--template",
|
|
446
|
-
"--alvo",
|
|
447
|
-
"--saida",
|
|
448
|
+
"--alvo", "-a",
|
|
449
|
+
"--saida", "-s",
|
|
448
450
|
"--estrutura",
|
|
449
451
|
"--framework",
|
|
450
452
|
"--namespace",
|
|
451
453
|
"--para",
|
|
452
454
|
]);
|
|
455
|
+
const ALIAS_OPCOES = {
|
|
456
|
+
"-a": "--alvo",
|
|
457
|
+
"-s": "--saida",
|
|
458
|
+
};
|
|
453
459
|
function obterPosicionais(args) {
|
|
454
460
|
const posicionais = [];
|
|
455
461
|
for (let indice = 0; indice < args.length; indice += 1) {
|
|
456
462
|
const atual = args[indice];
|
|
457
|
-
if (atual.startsWith("
|
|
463
|
+
if (atual.startsWith("-")) {
|
|
458
464
|
if (OPCOES_COM_VALOR.has(atual)) {
|
|
459
465
|
indice += 1;
|
|
460
466
|
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semacode/cli",
|
|
3
|
-
"version": "1.3.
|
|
4
|
-
"description": "CLI da Sema para validar contratos, medir drift e governar a navegacao operacional de agentes sobre software vivo em backend e front consumer.",
|
|
3
|
+
"version": "1.3.5",
|
|
5
4
|
"type": "module",
|
|
6
|
-
"
|
|
5
|
+
"description": "CLI da Sema para validar contratos, medir drift e governar a navegacao operacional de agentes sobre software vivo em backend e front consumer.",
|
|
7
6
|
"license": "MIT",
|
|
8
7
|
"repository": {
|
|
9
8
|
"type": "git",
|
|
@@ -28,47 +27,36 @@
|
|
|
28
27
|
"publishConfig": {
|
|
29
28
|
"access": "public"
|
|
30
29
|
},
|
|
30
|
+
"icon": "logo.png",
|
|
31
31
|
"bin": {
|
|
32
32
|
"sema": "dist/index.js"
|
|
33
33
|
},
|
|
34
34
|
"main": "dist/index.js",
|
|
35
35
|
"types": "dist/index.d.ts",
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
"exemplos",
|
|
40
|
-
"AGENTS.md",
|
|
41
|
-
"llms.txt",
|
|
42
|
-
"llms-full.txt",
|
|
43
|
-
"SEMA_BRIEF.md",
|
|
44
|
-
"SEMA_BRIEF.micro.txt",
|
|
45
|
-
"SEMA_BRIEF.curto.txt",
|
|
46
|
-
"SEMA_INDEX.json",
|
|
47
|
-
"logo.png",
|
|
48
|
-
"README.md",
|
|
49
|
-
"LICENSE"
|
|
50
|
-
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc -p tsconfig.json"
|
|
38
|
+
},
|
|
51
39
|
"dependencies": {
|
|
52
|
-
"@sema/nucleo": "
|
|
53
|
-
"@sema/gerador-dart": "
|
|
54
|
-
"@sema/gerador-lua": "
|
|
55
|
-
"@sema/gerador-python": "
|
|
56
|
-
"@sema/gerador-typescript": "
|
|
57
|
-
"@sema/gerador-javascript": "
|
|
58
|
-
"@sema/gerador-html": "
|
|
59
|
-
"@sema/gerador-css": "
|
|
60
|
-
"@sema/padroes": "
|
|
40
|
+
"@sema/nucleo": "file:../nucleo",
|
|
41
|
+
"@sema/gerador-dart": "file:../gerador-dart",
|
|
42
|
+
"@sema/gerador-lua": "file:../gerador-lua",
|
|
43
|
+
"@sema/gerador-python": "file:../gerador-python",
|
|
44
|
+
"@sema/gerador-typescript": "file:../gerador-typescript",
|
|
45
|
+
"@sema/gerador-javascript": "file:../gerador-javascript",
|
|
46
|
+
"@sema/gerador-html": "file:../gerador-html",
|
|
47
|
+
"@sema/gerador-css": "file:../gerador-css",
|
|
48
|
+
"@sema/padroes": "file:../padroes",
|
|
61
49
|
"typescript": "^5.8.3"
|
|
62
50
|
},
|
|
63
|
-
"
|
|
51
|
+
"bundleDependencies": [
|
|
64
52
|
"@sema/nucleo",
|
|
53
|
+
"@sema/padroes",
|
|
54
|
+
"@sema/gerador-typescript",
|
|
55
|
+
"@sema/gerador-python",
|
|
65
56
|
"@sema/gerador-dart",
|
|
66
57
|
"@sema/gerador-lua",
|
|
67
|
-
"@sema/gerador-python",
|
|
68
|
-
"@sema/gerador-typescript",
|
|
69
58
|
"@sema/gerador-javascript",
|
|
70
59
|
"@sema/gerador-html",
|
|
71
|
-
"@sema/gerador-css"
|
|
72
|
-
"@sema/padroes"
|
|
60
|
+
"@sema/gerador-css"
|
|
73
61
|
]
|
|
74
|
-
}
|
|
62
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export interface SimboloCppExtraido {
|
|
2
|
+
simbolo: string;
|
|
3
|
+
retorno?: string;
|
|
4
|
+
parametros: Array<{ nome: string; tipoTexto?: string; obrigatorio: boolean }>;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function extrairParametrosCpp(assinatura: string): Array<{ nome: string; tipoTexto?: string; obrigatorio: boolean }> {
|
|
8
|
+
return assinatura.split(",").map((parametroBruto) => {
|
|
9
|
+
const parametro = parametroBruto.trim();
|
|
10
|
+
if (!parametro || parametro === "void") {
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
|
|
14
|
+
const partes = semPadrao.split(/\s+/).filter(Boolean);
|
|
15
|
+
if (partes.length < 2) {
|
|
16
|
+
return undefined;
|
|
17
|
+
}
|
|
18
|
+
const nome = partes.at(-1)!.replace(/[&*]+$/, "");
|
|
19
|
+
const tipoTexto = partes.slice(0, -1).join(" ");
|
|
20
|
+
return {
|
|
21
|
+
nome,
|
|
22
|
+
tipoTexto,
|
|
23
|
+
obrigatorio: !parametro.includes("="),
|
|
24
|
+
};
|
|
25
|
+
}).filter((item): item is NonNullable<typeof item> => Boolean(item));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function extrairSimbolosCpp(codigo: string): SimboloCppExtraido[] {
|
|
29
|
+
const simbolos = new Map<string, SimboloCppExtraido>();
|
|
30
|
+
|
|
31
|
+
for (const match of codigo.matchAll(/(?:^|\n)\s*(?:inline\s+|static\s+|virtual\s+|constexpr\s+|friend\s+|extern\s+|template\s*<[^>]+>\s*)*(?:[\w:<>~*&]+\s+)+([A-Za-z_]\w*)::([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:const)?\s*(?:\{|;)/g)) {
|
|
32
|
+
const simbolo = `${match[1]!}.${match[2]!}`;
|
|
33
|
+
simbolos.set(simbolo, {
|
|
34
|
+
simbolo,
|
|
35
|
+
parametros: extrairParametrosCpp(match[3] ?? ""),
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
for (const match of codigo.matchAll(/(?:^|\n)\s*(?:inline\s+|static\s+|virtual\s+|constexpr\s+|friend\s+|extern\s+)*(?:[\w:<>~*&]+\s+)+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:const)?\s*(?:\{|;)/g)) {
|
|
40
|
+
const nome = match[1]!;
|
|
41
|
+
if (["if", "for", "while", "switch", "return"].includes(nome)) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!simbolos.has(nome)) {
|
|
45
|
+
simbolos.set(nome, {
|
|
46
|
+
simbolo: nome,
|
|
47
|
+
parametros: extrairParametrosCpp(match[2] ?? ""),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const pilhaClasses: string[] = [];
|
|
53
|
+
for (const linha of codigo.split(/\r?\n/)) {
|
|
54
|
+
const trim = linha.trim();
|
|
55
|
+
const classe = trim.match(/^(?:class|struct)\s+([A-Za-z_]\w*)/);
|
|
56
|
+
if (classe) {
|
|
57
|
+
pilhaClasses.push(classe[1]!);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (trim.startsWith("};") || trim === "}" || trim === "};") {
|
|
61
|
+
pilhaClasses.pop();
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const metodoClasse = trim.match(/^(?:inline\s+|static\s+|virtual\s+|constexpr\s+)*(?:[\w:<>~*&]+\s+)+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:const)?\s*\{/);
|
|
66
|
+
if (metodoClasse && pilhaClasses.length > 0) {
|
|
67
|
+
const nomeClasse = pilhaClasses[pilhaClasses.length - 1]!;
|
|
68
|
+
const nomeMetodo = metodoClasse[1]!;
|
|
69
|
+
if (!["if", "for", "while", "switch"].includes(nomeMetodo)) {
|
|
70
|
+
const simbolo = `${nomeClasse}.${nomeMetodo}`;
|
|
71
|
+
if (!simbolos.has(simbolo)) {
|
|
72
|
+
simbolos.set(simbolo, {
|
|
73
|
+
simbolo,
|
|
74
|
+
parametros: extrairParametrosCpp(metodoClasse[2] ?? ""),
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return [...simbolos.values()];
|
|
82
|
+
}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
export interface ParametroRotaBackend {
|
|
2
|
+
nome: string;
|
|
3
|
+
tipoSema: "Texto" | "Inteiro" | "Decimal" | "Id";
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
export interface SimboloDotnetExtraido {
|
|
7
|
+
simbolo: string;
|
|
8
|
+
retorno?: string;
|
|
9
|
+
parametros: Array<{ nome: string; tipoTexto?: string; obrigatorio: boolean }>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface RotaDotnetExtraida {
|
|
13
|
+
origem: "dotnet";
|
|
14
|
+
metodo: string;
|
|
15
|
+
caminho: string;
|
|
16
|
+
simbolo: string;
|
|
17
|
+
parametros: ParametroRotaBackend[];
|
|
18
|
+
retorno?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const METODOS_HTTP = new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
|
|
22
|
+
|
|
23
|
+
function normalizarCaminhoBase(caminho?: string): string | undefined {
|
|
24
|
+
if (!caminho) {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
return caminho.replace(/^\/+|\/+$/g, "");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function juntarCaminho(base: string | undefined, sufixo: string | undefined): string {
|
|
31
|
+
const partes = [base, sufixo]
|
|
32
|
+
.map((parte) => normalizarCaminhoBase(parte))
|
|
33
|
+
.filter((parte): parte is string => Boolean(parte));
|
|
34
|
+
return `/${partes.join("/")}`.replace(/\/+/g, "/");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function normalizarCaminhoAspNet(caminho: string, classe?: string, metodo?: string): string {
|
|
38
|
+
const controller = (classe ?? "").replace(/Controller$/i, "");
|
|
39
|
+
const action = metodo ?? "";
|
|
40
|
+
return caminho
|
|
41
|
+
.replace(/\[controller\]/gi, controller ? controller.toLowerCase() : "controller")
|
|
42
|
+
.replace(/\[action\]/gi, action ? action.toLowerCase() : "action")
|
|
43
|
+
.replace(/\{([^}:]+):[^}]+\}/g, "{$1}")
|
|
44
|
+
.replace(/\/+/g, "/");
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function mapearTipoRotaDotnet(tipo?: string): ParametroRotaBackend["tipoSema"] {
|
|
48
|
+
const normalizado = (tipo ?? "").toLowerCase();
|
|
49
|
+
if (/(^|\.)(int|int32|int64|long|short)$/.test(normalizado)) {
|
|
50
|
+
return "Inteiro";
|
|
51
|
+
}
|
|
52
|
+
if (/(^|\.)(float|double|decimal)$/.test(normalizado)) {
|
|
53
|
+
return "Decimal";
|
|
54
|
+
}
|
|
55
|
+
if (/guid|uuid|id$/i.test(normalizado)) {
|
|
56
|
+
return "Id";
|
|
57
|
+
}
|
|
58
|
+
return "Texto";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function extrairParametrosRota(caminho: string, assinatura: string): ParametroRotaBackend[] {
|
|
62
|
+
const tiposAssinatura = new Map<string, string>();
|
|
63
|
+
for (const parametroBruto of assinatura.split(",")) {
|
|
64
|
+
const parametro = parametroBruto.trim();
|
|
65
|
+
if (!parametro) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
|
|
69
|
+
const partes = semPadrao.split(/\s+/).filter(Boolean);
|
|
70
|
+
if (partes.length < 2) {
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
const nome = partes.at(-1)!;
|
|
74
|
+
const tipo = partes.slice(0, -1).join(" ");
|
|
75
|
+
tiposAssinatura.set(nome, tipo);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return [...caminho.matchAll(/\{([^}:]+)(?::[^}]+)?\}/g)].map((match) => {
|
|
79
|
+
const nome = match[1]!;
|
|
80
|
+
return {
|
|
81
|
+
nome,
|
|
82
|
+
tipoSema: mapearTipoRotaDotnet(tiposAssinatura.get(nome)),
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function extrairTextoAtributo(atributo: string): string | undefined {
|
|
88
|
+
return atributo.match(/"([^"]+)"/)?.[1];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function extrairMetodosAtributo(atributo: string): string[] {
|
|
92
|
+
const direto = atributo.match(/\[\s*Http(Get|Post|Put|Patch|Delete)\b/i)?.[1]?.toUpperCase();
|
|
93
|
+
if (direto && METODOS_HTTP.has(direto)) {
|
|
94
|
+
return [direto];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const bloco = atributo.match(/\bHttpMethods\.(Get|Post|Put|Patch|Delete)\b/gi)
|
|
98
|
+
?.map((item) => item.split(".").pop()?.toUpperCase() ?? "")
|
|
99
|
+
.filter((item) => METODOS_HTTP.has(item));
|
|
100
|
+
if (bloco && bloco.length > 0) {
|
|
101
|
+
return [...new Set(bloco)];
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const requestMapping = atributo.match(/\[\s*AcceptVerbs\(([^)]*)\)\s*\]/i)?.[1];
|
|
105
|
+
if (requestMapping) {
|
|
106
|
+
const encontrados = [...requestMapping.matchAll(/"([A-Za-z]+)"/g)]
|
|
107
|
+
.map((match) => match[1]!.toUpperCase())
|
|
108
|
+
.filter((item) => METODOS_HTTP.has(item));
|
|
109
|
+
if (encontrados.length > 0) {
|
|
110
|
+
return [...new Set(encontrados)];
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return [];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function contarChar(texto: string, alvo: string): number {
|
|
118
|
+
return [...texto].filter((char) => char === alvo).length;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function atualizarPilhaClasses<T extends { profundidade: number }>(pilha: T[], profundidade: number): void {
|
|
122
|
+
while (pilha.length > 0 && profundidade < pilha[pilha.length - 1]!.profundidade) {
|
|
123
|
+
pilha.pop();
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function extrairAtributos(linhas: string[], inicio: number): { atributos: string[]; proximoIndice: number } {
|
|
128
|
+
const atributos: string[] = [];
|
|
129
|
+
let indice = inicio;
|
|
130
|
+
|
|
131
|
+
while (indice < linhas.length) {
|
|
132
|
+
const linha = linhas[indice]!.trim();
|
|
133
|
+
if (!linha.startsWith("[")) {
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
let atual = linha;
|
|
137
|
+
let saldo = contarChar(linha, "[") - contarChar(linha, "]");
|
|
138
|
+
while (saldo > 0 && indice + 1 < linhas.length) {
|
|
139
|
+
indice += 1;
|
|
140
|
+
const complemento = linhas[indice]!.trim();
|
|
141
|
+
atual += ` ${complemento}`;
|
|
142
|
+
saldo += contarChar(complemento, "[") - contarChar(complemento, "]");
|
|
143
|
+
}
|
|
144
|
+
atributos.push(atual);
|
|
145
|
+
indice += 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { atributos, proximoIndice: indice };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function extrairSimbolosDotnet(codigo: string): SimboloDotnetExtraido[] {
|
|
152
|
+
const simbolos = new Map<string, SimboloDotnetExtraido>();
|
|
153
|
+
const linhas = codigo.split(/\r?\n/);
|
|
154
|
+
const pilhaClasses: Array<{ nome: string; profundidade: number }> = [];
|
|
155
|
+
let classePendente: { nome: string; profundidade: number } | undefined;
|
|
156
|
+
let profundidade = 0;
|
|
157
|
+
|
|
158
|
+
for (let indice = 0; indice < linhas.length; indice += 1) {
|
|
159
|
+
const linhaOriginal = linhas[indice]!;
|
|
160
|
+
const linha = linhaOriginal.trim();
|
|
161
|
+
if (classePendente && linha.startsWith("{")) {
|
|
162
|
+
pilhaClasses.push(classePendente);
|
|
163
|
+
classePendente = undefined;
|
|
164
|
+
}
|
|
165
|
+
if (!linha || linha.startsWith("//")) {
|
|
166
|
+
profundidade += contarChar(linhaOriginal, "{") - contarChar(linhaOriginal, "}");
|
|
167
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
168
|
+
continue;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const { atributos, proximoIndice } = extrairAtributos(linhas, indice);
|
|
172
|
+
if (atributos.length > 0) {
|
|
173
|
+
indice = proximoIndice;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const linhaEfetiva = (linhas[indice] ?? "").trim();
|
|
177
|
+
const classe = linhaEfetiva.match(/\bclass\s+([A-Za-z_]\w*)/);
|
|
178
|
+
if (classe) {
|
|
179
|
+
const entrada = { nome: classe[1]!, profundidade: profundidade + 1 };
|
|
180
|
+
if (linhaEfetiva.includes("{")) {
|
|
181
|
+
pilhaClasses.push(entrada);
|
|
182
|
+
} else {
|
|
183
|
+
classePendente = entrada;
|
|
184
|
+
}
|
|
185
|
+
profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
|
|
186
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const metodo = linhaEfetiva.match(/\b(?:public|internal|protected|private)\s+(?:static\s+|async\s+|virtual\s+|override\s+|sealed\s+|partial\s+)*([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/);
|
|
191
|
+
if (metodo) {
|
|
192
|
+
const classeAtual = pilhaClasses[pilhaClasses.length - 1];
|
|
193
|
+
const simbolo = classeAtual ? `${classeAtual.nome}.${metodo[2]!}` : metodo[2]!;
|
|
194
|
+
simbolos.set(simbolo, {
|
|
195
|
+
simbolo,
|
|
196
|
+
retorno: metodo[1]!.trim(),
|
|
197
|
+
parametros: metodo[3]!.split(",").flatMap((parametroBruto) => {
|
|
198
|
+
const parametro = parametroBruto.trim();
|
|
199
|
+
if (!parametro) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
|
|
203
|
+
const partes = semPadrao.split(/\s+/).filter(Boolean);
|
|
204
|
+
if (partes.length < 2) {
|
|
205
|
+
return [];
|
|
206
|
+
}
|
|
207
|
+
return [{
|
|
208
|
+
nome: partes.at(-1)!,
|
|
209
|
+
tipoTexto: partes.slice(0, -1).join(" "),
|
|
210
|
+
obrigatorio: !parametro.includes("="),
|
|
211
|
+
}];
|
|
212
|
+
}),
|
|
213
|
+
});
|
|
214
|
+
profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
|
|
215
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const funcaoLocal = linhaEfetiva.match(/\b([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*=>/);
|
|
220
|
+
if (funcaoLocal && atributos.length === 0 && pilhaClasses.length === 0) {
|
|
221
|
+
const simbolo = funcaoLocal[2]!;
|
|
222
|
+
simbolos.set(simbolo, {
|
|
223
|
+
simbolo,
|
|
224
|
+
retorno: funcaoLocal[1]!.trim(),
|
|
225
|
+
parametros: [],
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const funcaoTopo = linhaEfetiva.match(/\b(?:static\s+)?([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:\{|$)/);
|
|
230
|
+
if (funcaoTopo && atributos.length === 0 && pilhaClasses.length === 0 && !["if", "for", "while", "switch"].includes(funcaoTopo[2]!)) {
|
|
231
|
+
const simbolo = funcaoTopo[2]!;
|
|
232
|
+
if (!simbolos.has(simbolo)) {
|
|
233
|
+
simbolos.set(simbolo, {
|
|
234
|
+
simbolo,
|
|
235
|
+
retorno: funcaoTopo[1]!.trim(),
|
|
236
|
+
parametros: funcaoTopo[3]!.split(",").flatMap((parametroBruto) => {
|
|
237
|
+
const parametro = parametroBruto.trim();
|
|
238
|
+
if (!parametro) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
|
|
242
|
+
const partes = semPadrao.split(/\s+/).filter(Boolean);
|
|
243
|
+
if (partes.length < 2) {
|
|
244
|
+
return [];
|
|
245
|
+
}
|
|
246
|
+
return [{
|
|
247
|
+
nome: partes.at(-1)!,
|
|
248
|
+
tipoTexto: partes.slice(0, -1).join(" "),
|
|
249
|
+
obrigatorio: !parametro.includes("="),
|
|
250
|
+
}];
|
|
251
|
+
}),
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
|
|
257
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return [...simbolos.values()];
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function extrairRotasDotnet(codigo: string): RotaDotnetExtraida[] {
|
|
264
|
+
const rotas = new Map<string, RotaDotnetExtraida>();
|
|
265
|
+
const linhas = codigo.split(/\r?\n/);
|
|
266
|
+
const pilhaClasses: Array<{ nome: string; profundidade: number; rotaBase?: string; apiController: boolean }> = [];
|
|
267
|
+
let classePendente: { nome: string; profundidade: number; rotaBase?: string; apiController: boolean } | undefined;
|
|
268
|
+
let profundidade = 0;
|
|
269
|
+
|
|
270
|
+
for (let indice = 0; indice < linhas.length; indice += 1) {
|
|
271
|
+
const linhaOriginal = linhas[indice]!;
|
|
272
|
+
const linha = linhaOriginal.trim();
|
|
273
|
+
if (classePendente && linha.startsWith("{")) {
|
|
274
|
+
pilhaClasses.push(classePendente);
|
|
275
|
+
classePendente = undefined;
|
|
276
|
+
}
|
|
277
|
+
if (!linha || linha.startsWith("//")) {
|
|
278
|
+
profundidade += contarChar(linhaOriginal, "{") - contarChar(linhaOriginal, "}");
|
|
279
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
const { atributos, proximoIndice } = extrairAtributos(linhas, indice);
|
|
284
|
+
if (atributos.length > 0) {
|
|
285
|
+
indice = proximoIndice;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const linhaEfetiva = (linhas[indice] ?? "").trim();
|
|
289
|
+
const classe = linhaEfetiva.match(/\bclass\s+([A-Za-z_]\w*)/);
|
|
290
|
+
if (classe) {
|
|
291
|
+
const rotaBase = atributos
|
|
292
|
+
.map((atributo) => extrairTextoAtributo(atributo))
|
|
293
|
+
.find(Boolean);
|
|
294
|
+
const entrada = {
|
|
295
|
+
nome: classe[1]!,
|
|
296
|
+
profundidade: profundidade + 1,
|
|
297
|
+
rotaBase,
|
|
298
|
+
apiController: atributos.some((atributo) => /\[\s*ApiController\s*\]/i.test(atributo)),
|
|
299
|
+
};
|
|
300
|
+
if (linhaEfetiva.includes("{")) {
|
|
301
|
+
pilhaClasses.push(entrada);
|
|
302
|
+
} else {
|
|
303
|
+
classePendente = entrada;
|
|
304
|
+
}
|
|
305
|
+
profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
|
|
306
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const classeAtual = pilhaClasses[pilhaClasses.length - 1];
|
|
311
|
+
const metodo = linhaEfetiva.match(/\b(?:public|internal|protected)\s+(?:async\s+|virtual\s+|override\s+|static\s+)*([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/);
|
|
312
|
+
if (metodo && classeAtual) {
|
|
313
|
+
const atributosMetodo = atributos.filter((atributo) => /\[\s*(?:Http|AcceptVerbs)/i.test(atributo));
|
|
314
|
+
for (const atributo of atributosMetodo) {
|
|
315
|
+
const metodos = extrairMetodosAtributo(atributo);
|
|
316
|
+
const rotaMetodo = extrairTextoAtributo(atributo);
|
|
317
|
+
for (const httpMetodo of metodos) {
|
|
318
|
+
const caminho = normalizarCaminhoAspNet(
|
|
319
|
+
juntarCaminho(classeAtual.rotaBase, rotaMetodo),
|
|
320
|
+
classeAtual.nome,
|
|
321
|
+
metodo[2]!,
|
|
322
|
+
);
|
|
323
|
+
const registro: RotaDotnetExtraida = {
|
|
324
|
+
origem: "dotnet",
|
|
325
|
+
metodo: httpMetodo,
|
|
326
|
+
caminho,
|
|
327
|
+
simbolo: `${classeAtual.nome}.${metodo[2]!}`,
|
|
328
|
+
parametros: extrairParametrosRota(caminho, metodo[3] ?? ""),
|
|
329
|
+
retorno: metodo[1]!.trim(),
|
|
330
|
+
};
|
|
331
|
+
rotas.set(`${registro.metodo}:${registro.caminho}:${registro.simbolo}`, registro);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
for (const match of linhaEfetiva.matchAll(/\b\w+\.Map(Get|Post|Put|Patch|Delete)\(\s*"([^"]+)"\s*,\s*([A-Za-z_][\w.]*)/g)) {
|
|
337
|
+
const httpMetodo = match[1]!.toUpperCase();
|
|
338
|
+
const caminho = normalizarCaminhoAspNet(match[2]!);
|
|
339
|
+
const simbolo = match[3]!;
|
|
340
|
+
const registro: RotaDotnetExtraida = {
|
|
341
|
+
origem: "dotnet",
|
|
342
|
+
metodo: httpMetodo,
|
|
343
|
+
caminho,
|
|
344
|
+
simbolo,
|
|
345
|
+
parametros: extrairParametrosRota(caminho, ""),
|
|
346
|
+
};
|
|
347
|
+
rotas.set(`${registro.metodo}:${registro.caminho}:${registro.simbolo}`, registro);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
|
|
351
|
+
atualizarPilhaClasses(pilhaClasses, profundidade);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return [...rotas.values()];
|
|
355
|
+
}
|