diff --git a/infraestrutura/resposta.ts b/infraestrutura/resposta.ts
index aaffd85..52e93f9 100644
--- a/infraestrutura/resposta.ts
+++ b/infraestrutura/resposta.ts
@@ -1,8 +1,9 @@
import { Simbolo } from '@designliquido/delegua/fontes/lexador';
import { DefinirValor, FuncaoConstruto, Isto, Literal, Variavel } from '@designliquido/delegua/fontes/construtos';
-import { Expressao, Retorna } from '@designliquido/delegua/fontes/declaracoes';
+import { Expressao, PropriedadeClasse, Retorna } from '@designliquido/delegua/fontes/declaracoes';
import { DeleguaClasse, DeleguaFuncao } from '@designliquido/delegua/fontes/estruturas';
import { ParametroInterface } from '@designliquido/delegua/fontes/interfaces';
+
import { GeradorExpressoes } from './utilidades/gerador-expressoes';
/**
@@ -13,12 +14,43 @@ import { GeradorExpressoes } from './utilidades/gerador-expressoes';
export class Resposta extends DeleguaClasse {
constructor() {
const metodos = {};
+ const propriedades = [
+ new PropriedadeClasse(
+ new Simbolo('IDENTIFICADOR', 'mensagem', null, -1, -1),
+ 'texto'
+ ),
+ new PropriedadeClasse(
+ new Simbolo('IDENTIFICADOR', 'statusHttp', null, -1, -1),
+ 'numero'
+ ),
+ new PropriedadeClasse(
+ new Simbolo('IDENTIFICADOR', 'valores', null, -1, -1),
+ 'dicionário'
+ ),
+ new PropriedadeClasse(
+ new Simbolo('IDENTIFICADOR', 'visao', null, -1, -1),
+ 'texto'
+ )
+ ];
+
+ // Há duas formas de construção de métodos apenas usando
+ // estruturas de alto nível: declarando cada uma manualmente,
+ // ou usando o gerador de expressões.
+ // O exemplo abaixo utiliza o gerador de expressões.
+ // Seria o equivalente à seguinte implementação em Delégua:
- // Todo @Italo: Verificar se isso é melhor para instrumentar métodos.
- /* const geradorExpressoes = new GeradorExpressoes();
- metodos['enviar'] = geradorExpressoes.gerarMetodo('enviar',
- geradorExpressoes.gerarDeclaracao(
- [geradorExpressoes.gerarParametro('mensagem', 'numero')],
+ // classe Resposta {
+ // // Outros método e propriedades aqui
+ // enviar(mensagem: texto) {
+ // isto.mensagem = mensagem
+ // retorna isto
+ // }
+ // }
+
+ const geradorExpressoes = new GeradorExpressoes();
+ metodos['enviar'] = geradorExpressoes.gerarMetodo('enviar',
+ geradorExpressoes.gerarConstrutoFuncao(
+ [geradorExpressoes.gerarParametro('mensagem', 'texto')],
[
geradorExpressoes.gerarAtribuicaoValorEmPropriedadeClasse(
'mensagem',
@@ -27,39 +59,20 @@ export class Resposta extends DeleguaClasse {
geradorExpressoes.gerarRetornoDeFuncao('isto')
]
)
- ); */
-
- metodos['enviar'] = new DeleguaFuncao(
- 'enviar',
- new FuncaoConstruto(
- -1,
- -1,
- [
- {
- abrangencia: 'padrao',
- tipo: 'numero',
- nome: new Simbolo('IDENTIFICADOR', 'mensagem', null, -1, -1)
- } as ParametroInterface
- ],
- [
- new Expressao(
- new DefinirValor(
- -1,
- -1,
- new Isto(-1, -1, new Simbolo('ISTO', 'isto', null, -1, -1)),
- new Simbolo('IDENTIFICADOR', 'mensagem', null, -1, -1),
- new Variavel(-1, new Simbolo('IDENTIFICADOR', 'mensagem', null, -1, -1))
- )
- ),
- new Retorna(
- new Simbolo('IDENTIFICADOR', 'qualquerCoisa', null, -1, -1),
- new Variavel(-1, new Simbolo('IDENTIFICADOR', 'isto', null, -1, -1))
- )
- ]
- ),
- null,
- false
);
+
+ // O exemplo abaixo gera um método `status` declarando manualmente
+ // todas as estruturas de alto nível de Delégua.
+ // Seria o equivalente à seguinte implementação:
+
+ // classe Resposta {
+ // // Outros método e propriedades aqui
+ // status(statusHttp: numero) {
+ // isto.statusHttp = statusHttp
+ // retorna isto
+ // }
+ // }
+
metodos['status'] = new DeleguaFuncao(
'status',
new FuncaoConstruto(
@@ -91,7 +104,66 @@ export class Resposta extends DeleguaClasse {
null,
false
);
- metodos['lmht'] = new DeleguaFuncao(
+
+ // O exemplo abaixo gera um método `lmht` utilizando o gerador de expressões.
+ // Seria o equivalente à seguinte implementação:
+
+ // classe Resposta {
+ // visao: texto
+ // valores: dicionário
+ //
+ // lmht(*visaoEValores) {
+ // se visaoEValores.tamanho() > 1 {
+ // isto.visao = visaoEValores[0]
+ // isto.valores = visaoEValores[1]
+ // } senão {
+ // isto.valores = visaoEValores[0]
+ // }
+ //
+ // retorna isto
+ // }
+ // }
+
+ metodos['lmht'] = geradorExpressoes.gerarMetodo('lmht',
+ geradorExpressoes.gerarConstrutoFuncao(
+ [geradorExpressoes.gerarParametro('visaoEValores', 'vetor', 'multiplo')],
+ [
+ geradorExpressoes.gerarAtribuicaoValorEmPropriedadeClasse(
+ 'lmht',
+ geradorExpressoes.gerarLiteral(true)
+ ),
+ geradorExpressoes.gerarDeclaracaoSe(
+ geradorExpressoes.gerarConstrutoBinario(
+ geradorExpressoes.gerarChamada(
+ geradorExpressoes.gerarAcessoMetodoOuPropriedade(
+ geradorExpressoes.gerarReferenciaVariavel('visaoEValores'),
+ 'tamanho'
+ )
+ ),
+ geradorExpressoes.gerarOperadorComparacao('maior'),
+ geradorExpressoes.gerarLiteral(1)
+ ),
+ geradorExpressoes.gerarBlocoEscopo([ // Se
+ geradorExpressoes.gerarAtribuicaoValorEmPropriedadeClasse(
+ 'visao',
+ geradorExpressoes.gerarAcessoIndiceVariavel('visaoEValores', 0)
+ ),
+ geradorExpressoes.gerarAtribuicaoValorEmPropriedadeClasse(
+ 'valores',
+ geradorExpressoes.gerarAcessoIndiceVariavel('visaoEValores', 1)
+ )
+ ]),
+ geradorExpressoes.gerarBlocoEscopo([ // Senão
+ geradorExpressoes.gerarAtribuicaoValorEmPropriedadeClasse(
+ 'valores',
+ geradorExpressoes.gerarAcessoIndiceVariavel('visaoEValores', 0)
+ ),
+ ])
+ ),
+ geradorExpressoes.gerarRetornoDeFuncao('isto')
+ ])
+ );
+ /* metodos['lmht'] = new DeleguaFuncao(
'lmht',
new FuncaoConstruto(
-1,
@@ -130,7 +202,12 @@ export class Resposta extends DeleguaClasse {
),
null,
false
+ ); */
+ super(
+ new Simbolo('IDENTIFICADOR', 'Resposta', null, -1, -1),
+ null,
+ metodos,
+ propriedades
);
- super(new Simbolo('IDENTIFICADOR', 'Resposta', null, -1, -1), null, metodos);
}
}
diff --git a/infraestrutura/utilidades/gerador-expressoes.ts b/infraestrutura/utilidades/gerador-expressoes.ts
index bbb9edd..4ee70ec 100644
--- a/infraestrutura/utilidades/gerador-expressoes.ts
+++ b/infraestrutura/utilidades/gerador-expressoes.ts
@@ -1,8 +1,8 @@
import { DeleguaFuncao } from '@designliquido/delegua/fontes/estruturas';
-import { DefinirValor, FuncaoConstruto, Isto, Construto, Variavel } from '@designliquido/delegua/fontes/construtos';
-import { ParametroInterface } from '@designliquido/delegua/fontes/interfaces';
+import { DefinirValor, FuncaoConstruto, Isto, Construto, Variavel, Binario, Literal, Chamada, AcessoMetodoOuPropriedade, AcessoIndiceVariavel } from '@designliquido/delegua/fontes/construtos';
+import { ParametroInterface, SimboloInterface } from '@designliquido/delegua/fontes/interfaces';
import { Simbolo } from '@designliquido/delegua/fontes/lexador';
-import { Expressao, Retorna, Declaracao } from '@designliquido/delegua/fontes/declaracoes';
+import { Expressao, Retorna, Declaracao, Se, Bloco } from '@designliquido/delegua/fontes/declaracoes';
/**
* O gerador de expressões é uma classe facilitadora para a criação de
@@ -11,17 +11,74 @@ import { Expressao, Retorna, Declaracao } from '@designliquido/delegua/fontes/de
*/
export class GeradorExpressoes {
+ gerarAcessoIndiceVariavel(variavel: string, indice: number): AcessoIndiceVariavel {
+ return new AcessoIndiceVariavel(
+ -1,
+ new Variavel(
+ -1,
+ new Simbolo('IDENTIFICADOR', variavel, null, -1, -1)
+ ),
+ new Literal(-1, -1, indice),
+ new Simbolo('COLCHETE_DIREITO', ']', null, -1, -1)
+ );
+ }
+
+ gerarAcessoMetodoOuPropriedade(objeto: Variavel, metodoOuPropriedade: string): AcessoMetodoOuPropriedade {
+ return new AcessoMetodoOuPropriedade(
+ -1,
+ objeto,
+ new Simbolo('IDENTIFICADOR', metodoOuPropriedade, null, -1, -1)
+ );
+ }
+
+ gerarBlocoEscopo(declaracoes: Declaracao[]): Bloco {
+ return new Bloco(-1, -1, declaracoes);
+ }
+
+ gerarChamada(entidadeChamada: AcessoMetodoOuPropriedade, argumentos: any[] = []): Chamada {
+ return new Chamada(-1, entidadeChamada, null, argumentos);
+ }
+
+ gerarConstrutoBinario(ladoEsquerdo: Construto, operador: SimboloInterface, ladoDireito: Construto) {
+ return new Binario(-1, ladoEsquerdo, operador, ladoDireito);
+ }
+
+ gerarConstrutoFuncao(parametros: ParametroInterface[], corpo: Declaracao[]): FuncaoConstruto {
+ return new FuncaoConstruto(-1, -1, parametros, corpo);
+ }
+
+ gerarDeclaracaoSe(condicao: Construto, caminhoEntao: Declaracao, caminhoSenao?: Declaracao) {
+ return new Se(condicao, caminhoEntao, [], caminhoSenao);
+ }
+
+ gerarLiteral(valor: any) {
+ return new Literal(-1, -1, valor);
+ }
+
gerarMetodo(nomeMetodo: string, declaracao: FuncaoConstruto): DeleguaFuncao {
return new DeleguaFuncao(nomeMetodo, declaracao, null, false);
}
- gerarDeclaracao(parametros: ParametroInterface[], corpo: Declaracao[]): FuncaoConstruto {
- return new FuncaoConstruto(-1, -1, parametros, corpo);
+ gerarOperadorComparacao(tipo: 'maior' | 'menor' | 'maiorOuIgual' | 'menorOuIgual' | 'igual' | 'diferente'): SimboloInterface {
+ switch (tipo) {
+ case 'maior':
+ return new Simbolo('MAIOR', '>', null, -1, -1);
+ case 'menor':
+ return new Simbolo('MENOR', '<', null, -1, -1);
+ case 'maiorOuIgual':
+ return new Simbolo('MAIOR_IGUAL', '>=', null, -1, -1);
+ case 'menorOuIgual':
+ return new Simbolo('MENOR_IGUAL', '<=', null, -1, -1);
+ case 'igual':
+ return new Simbolo('IGUAL_IGUAL', '==', null, -1, -1);
+ case 'diferente':
+ return new Simbolo('DIFERENTE', '!=', null, -1, -1);
+ }
}
- gerarParametro(nome: string, tipo: string): ParametroInterface {
+ gerarParametro(nome: string, tipo: string, abrangencia: 'padrao' | 'multiplo' = 'padrao'): ParametroInterface {
return {
- abrangencia: 'padrao',
+ abrangencia: abrangencia,
tipo: tipo,
nome: new Simbolo('IDENTIFICADOR', nome, null, -1, -1)
} as ParametroInterface;
diff --git a/interface-linha-comando/gerar/gerador-rotas.ts b/interface-linha-comando/gerar/gerador-rotas.ts
index fc70e9c..df92a43 100644
--- a/interface-linha-comando/gerar/gerador-rotas.ts
+++ b/interface-linha-comando/gerar/gerador-rotas.ts
@@ -64,7 +64,7 @@ export class GeradorRotas {
* @returns O caminho do arquivo de rotas no sistema de arquivos.
*/
private criarNovasRotasComId(declaracaoModelo: Classe, diretorioRotas: string): string {
- const conteudoSelecionarUm = `liquido.rotaGet(funcao(requisicao, resposta) {\n resposta.enviar(requisicao.params.id)\n})\n\n`;
+ const conteudoSelecionarUm = this.criarRotaSelecionarUm(declaracaoModelo);
const conteudoAtualizar = `liquido.rotaPut(funcao(requisicao, resposta) {\n resposta.lmht({ "titulo": "Liquido" })\n})\n\n`;
const conteudoExcluir = `liquido.rotaDelete(funcao(requisicao, resposta) {\n resposta.lmht({ "titulo": "Liquido" })\n})\n\n`;
const conteudoRotas = `${conteudoSelecionarUm}${conteudoAtualizar}${conteudoExcluir}`;
@@ -95,4 +95,21 @@ export class GeradorRotas {
`${" ".repeat(this.indentacao)}})\n` +
`})\n\n`;
}
+
+ private criarRotaSelecionarUm(declaracaoModelo: Classe) {
+ // Isso aqui não vai ficar assim.
+ // É preciso montar as partes de dados antes.
+ const dadosTestes = [];
+ for (const propriedade of declaracaoModelo.propriedades) {
+ dadosTestes.push(`"${propriedade.nome.lexema}": "Teste"`);
+ }
+
+ return `liquido.rotaGet(funcao(requisicao, resposta) {\n` +
+ `${" ".repeat(this.indentacao)}resposta.lmht("detalhes", {\n` +
+ `${" ".repeat(this.indentacao * 2)}${dadosTestes.reduce(
+ (acumulador, elemento) => acumulador + ', ' + elemento
+ )}\n` +
+ `${" ".repeat(this.indentacao)}})\n` +
+ `})\n\n`;
+ }
}
\ No newline at end of file
diff --git a/interface-linha-comando/gerar/gerador-visoes.ts b/interface-linha-comando/gerar/gerador-visoes.ts
index 563c1bb..c1e4eea 100644
--- a/interface-linha-comando/gerar/gerador-visoes.ts
+++ b/interface-linha-comando/gerar/gerador-visoes.ts
@@ -31,7 +31,7 @@ export class GeradorVisoes {
break;
case 'selecionarUm':
caminhoVisao = caminho.join(diretorioVisoes, 'detalhes.lmht');
- corpo = ' Teste\n';
+ corpo = `${" ".repeat(this.indentacao)}\n${this.corpoDetalhes(declaracaoModelo)}\n${" ".repeat(this.indentacao)}\n`;
break;
case 'adicionar':
caminhoVisao = caminho.join(diretorioVisoes, 'adicionar.lmht');
@@ -94,4 +94,27 @@ export class GeradorVisoes {
return `${" ".repeat(this.indentacao * 2)}\n${cabecaTabela}\n${corpoTabela}\n${" ".repeat(this.indentacao * 2)}`;
}
+
+ /**
+ * Função que gera o corpo de `detalhes.lmht` de cada visão gerada por linha de comando.
+ * @param {Classe} declaracaoModelo A declaração do modelo de dados, com suas propriedades e definições.
+ * @returns {string} Um trecho em LMHT com a estrutura do corpo da página.
+ */
+ private corpoDetalhes(declaracaoModelo: Classe): string {
+ const titulo = `${" ".repeat(this.indentacao * 2)}Detalhes de ${declaracaoModelo.simbolo.lexema}\n`;
+
+ const listaPropriedades: string[] = [];
+ for (const propriedade of declaracaoModelo.propriedades) {
+ listaPropriedades.push(" ".repeat(this.indentacao * 3) + `${propriedade.nome.lexema}`);
+ listaPropriedades.push(" ".repeat(this.indentacao * 3) + `{{${propriedade.nome.lexema}}}`);
+ }
+
+ const relacaoPropriedades = `${" ".repeat(this.indentacao * 2)}\n` +
+ listaPropriedades.reduce(
+ (acumulador, elemento) => acumulador + '\n' + elemento
+ ) +
+ `\n${" ".repeat(this.indentacao * 2)}\n`;
+
+ return `${titulo}${relacaoPropriedades}`;
+ }
}
diff --git a/liquido.ts b/liquido.ts
index a8937ac..08f6a9f 100644
--- a/liquido.ts
+++ b/liquido.ts
@@ -337,7 +337,17 @@ export class Liquido implements LiquidoInterface {
try {
if (valor.propriedades.lmht) {
- const resultadoFormatacaoLmht = await this.formatadorLmht.formatar(caminhoRota, valor.propriedades.valores);
+ let visao: string = caminhoRota;
+ // Verifica se foi definida uma preferência de visão.
+ // Se não foi, usa o sufixo da rota como visão correspondente.
+ // Por exemplo, `/rotas/inicial.delegua` tem como visão correspondente `/visoes/inicial.lmht`.
+ if (valor.propriedades.visao) {
+ const partesRota = caminhoRota.split('/');
+ partesRota.pop();
+ visao = partesRota.join('/') + '/' + valor.propriedades.visao;
+ }
+
+ const resultadoFormatacaoLmht = await this.formatadorLmht.formatar(visao, valor.propriedades.valores);
return {
corpoRetorno: resultadoFormatacaoLmht,
statusHttp: statusHttp
diff --git a/package.json b/package.json
index ca86a50..aa1c2c0 100644
--- a/package.json
+++ b/package.json
@@ -39,7 +39,7 @@
"swagger": "tsoa spec"
},
"dependencies": {
- "@designliquido/delegua-node": "^0.29.1",
+ "@designliquido/delegua-node": "^0.29.2",
"@designliquido/flexoes": "^0.1.0",
"@designliquido/foles": "^0.6.1",
"@designliquido/lincones-sqlite": "^0.0.2",
diff --git a/rotas/blog/inicial.delegua b/rotas/blog/inicial.delegua
index 97da1fb..35f4e3d 100644
--- a/rotas/blog/inicial.delegua
+++ b/rotas/blog/inicial.delegua
@@ -1,3 +1,3 @@
liquido.rotaGet(funcao(requisicao, resposta) {
resposta.lmht({ "titulo": "Blog" })
-})
\ No newline at end of file
+})
diff --git a/yarn.lock b/yarn.lock
index abd8600..69170b5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -304,21 +304,21 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
-"@designliquido/delegua-node@^0.29.1":
- version "0.29.1"
- resolved "https://registry.yarnpkg.com/@designliquido/delegua-node/-/delegua-node-0.29.1.tgz#815a81f15dcf7688d2b7cb670f0f95410aa1c933"
- integrity sha512-h02pyDi+Yq6cYziabqKeY72zoeM26y0+KaLi2DQrW3MdhdHi6HHlOTXSAVuypSOB7XsGQodi+mvr/IpfMj1hWA==
+"@designliquido/delegua-node@^0.29.2":
+ version "0.29.2"
+ resolved "https://registry.yarnpkg.com/@designliquido/delegua-node/-/delegua-node-0.29.2.tgz#828bd88481ee5e7201a789d0685d8fc44cadde62"
+ integrity sha512-Xn7lSG2vixj2tfL7QKyhGUONk8QkxmW4mcoYwO3lj/tgIL6NJzx/8LRf0wqR7aBlYBWqrnAnYvMbl0qlDsDcjg==
dependencies:
- "@designliquido/delegua" "0.29.1"
+ "@designliquido/delegua" "0.29.2"
chalk "4.1.2"
commander "^9.4.1"
json-colorizer "^2.2.2"
lodash.clonedeep "^4.5.0"
-"@designliquido/delegua@0.29.1":
- version "0.29.1"
- resolved "https://registry.yarnpkg.com/@designliquido/delegua/-/delegua-0.29.1.tgz#9d2953915da19588b0f47b86df8a5dbfd4aa1ec9"
- integrity sha512-M+gqB3vJ9XWldJorCQLsN2UgLTLnyPRrnS5uRpqI1lLyszbcxOKGNPGYfgtrS7nokttcE3B0NfOA9eztwjV2Fg==
+"@designliquido/delegua@0.29.2":
+ version "0.29.2"
+ resolved "https://registry.yarnpkg.com/@designliquido/delegua/-/delegua-0.29.2.tgz#da5eb931deede8a5cbf8fa8b95f65379972ae5ee"
+ integrity sha512-sdGD+b1gJBZqhfppk2WTHIaQviUylu9907kKHAXRXIEuQgUfi1GA/EFZhvr3CvHemhmbo9kQclN4JQEY+zBKUQ==
dependencies:
antlr4ts "^0.5.0-alpha.4"
browser-process-hrtime "^1.0.0"