@designliquido/delegua 1.22.2 → 1.23.1

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/umd/delegua.js CHANGED
@@ -520,13 +520,15 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
520
520
  this.funcoes = {};
521
521
  this.classesDeclaradas = new Set();
522
522
  this.classesRegistradas = new Map();
523
- this.classesExternasConhecidas = new Set();
523
+ this.classesExternasRegistradas = new Map();
524
524
  this.classeAtualEmAnalise = null;
525
525
  this.atual = 0;
526
526
  this.diagnosticos = [];
527
527
  }
528
- definirClassesExternasConhecidas(classesExternasConhecidas) {
529
- this.classesExternasConhecidas = new Set(classesExternasConhecidas);
528
+ registrarClassesExternas(classes) {
529
+ for (const classe of classes) {
530
+ this.classesExternasRegistradas.set(classe.simbolo.lexema, classe);
531
+ }
530
532
  }
531
533
  verificarTipoAtribuido(declaracao) {
532
534
  if (declaracao.tipo) {
@@ -1304,8 +1306,11 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
1304
1306
  this.verificarLadoLogico(logico.esquerda);
1305
1307
  return Promise.resolve();
1306
1308
  }
1307
- verificarChamada(chamada) {
1309
+ async verificarChamada(chamada) {
1308
1310
  switch (chamada.entidadeChamada.constructor) {
1311
+ case construtos_1.AcessoMetodoOuPropriedade:
1312
+ await chamada.entidadeChamada.aceitar(this);
1313
+ break;
1309
1314
  case construtos_1.Variavel:
1310
1315
  let entidadeChamadaVariavel = chamada.entidadeChamada;
1311
1316
  const nomeFuncao = entidadeChamadaVariavel.simbolo.lexema;
@@ -1692,7 +1697,7 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
1692
1697
  this.erro(superClasseVariavel.simbolo, `A classe '${declaracao.simbolo.lexema}' não pode herdar de si mesma.`);
1693
1698
  }
1694
1699
  else if (!this.classesDeclaradas.has(nomeSuperclasse) &&
1695
- !this.classesExternasConhecidas.has(nomeSuperclasse)) {
1700
+ !this.classesRegistradas.has(nomeSuperclasse)) {
1696
1701
  this.erro(superClasseVariavel.simbolo, `Superclasse '${nomeSuperclasse}' não foi declarada.`);
1697
1702
  }
1698
1703
  }
@@ -1861,8 +1866,8 @@ class AnalisadorSemantico extends analisador_semantico_base_1.AnalisadorSemantic
1861
1866
  }
1862
1867
  async analisar(declaracoes) {
1863
1868
  this.gerenciadorEscopos = new gerenciador_escopos_1.GerenciadorEscopos();
1864
- this.classesDeclaradas = new Set();
1865
- this.classesRegistradas = new Map();
1869
+ this.classesDeclaradas = new Set(this.classesExternasRegistradas.keys());
1870
+ this.classesRegistradas = new Map(this.classesExternasRegistradas);
1866
1871
  this.classeAtualEmAnalise = null;
1867
1872
  this.atual = 0;
1868
1873
  this.diagnosticos = [];
@@ -13763,29 +13768,17 @@ function simboloAtual(interpretador) {
13763
13768
  function construirModuloDeTestes(interpretador, registro) {
13764
13769
  const modulo = new modulo_1.DeleguaModulo('testes');
13765
13770
  modulo.componentes['afirmar'] = (0, modulo_afirmar_1.construirModuloAfirmar)();
13766
- modulo.componentes['grupo'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13767
- const nome = interpretador.resolverValor(nomeRaw);
13768
- const funcao = interpretador.resolverValor(funcaoRaw);
13769
- const suiteAnterior = registro.suiteAtual;
13770
- registro.suiteAtual = suiteAnterior ? `${suiteAnterior} > ${nome}` : nome;
13771
- const emDeclaracaoTenteAnterior = interpretador.emDeclaracaoTente;
13772
- interpretador.emDeclaracaoTente = true;
13773
- try {
13774
- await funcao.chamar(interpretador, [], null);
13775
- }
13776
- finally {
13777
- registro.suiteAtual = suiteAnterior;
13778
- interpretador.emDeclaracaoTente = emDeclaracaoTenteAnterior;
13779
- }
13780
- });
13781
- modulo.componentes['teste'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13782
- const nome = interpretador.resolverValor(nomeRaw);
13783
- const funcao = interpretador.resolverValor(funcaoRaw);
13771
+ async function executarTeste(nome, fn) {
13784
13772
  const inicio = Date.now();
13785
13773
  const emDeclaracaoTenteAnterior = interpretador.emDeclaracaoTente;
13786
13774
  interpretador.emDeclaracaoTente = true;
13775
+ for (const escopo of registro.pilhaEscopos) {
13776
+ for (const h of escopo.antesDeCada) {
13777
+ await h.chamar(interpretador, [], null);
13778
+ }
13779
+ }
13787
13780
  try {
13788
- await funcao.chamar(interpretador, [], null);
13781
+ await fn.chamar(interpretador, [], null);
13789
13782
  registro.resultados.push({
13790
13783
  nomeSuite: registro.suiteAtual,
13791
13784
  nomeTeste: nome,
@@ -13803,9 +13796,134 @@ function construirModuloDeTestes(interpretador, registro) {
13803
13796
  });
13804
13797
  }
13805
13798
  finally {
13799
+ for (const escopo of [...registro.pilhaEscopos].reverse()) {
13800
+ for (const h of escopo.depoisDeCada) {
13801
+ await h.chamar(interpretador, [], null);
13802
+ }
13803
+ }
13804
+ interpretador.emDeclaracaoTente = emDeclaracaoTenteAnterior;
13805
+ }
13806
+ }
13807
+ async function executarGrupo(nome, fn) {
13808
+ const suiteAnterior = registro.suiteAtual;
13809
+ registro.suiteAtual = suiteAnterior ? `${suiteAnterior} > ${nome}` : nome;
13810
+ const escopo = {
13811
+ antesDeCada: [],
13812
+ antesDeTodos: [],
13813
+ depoisDeCada: [],
13814
+ depoisDeTodos: [],
13815
+ itensColetados: [],
13816
+ temApenas: false,
13817
+ };
13818
+ registro.pilhaEscopos.push(escopo);
13819
+ const modoColetarAnterior = registro.modoColeta;
13820
+ registro.modoColeta = true;
13821
+ const emDeclaracaoTenteAnterior = interpretador.emDeclaracaoTente;
13822
+ interpretador.emDeclaracaoTente = true;
13823
+ try {
13824
+ await fn.chamar(interpretador, [], null);
13825
+ registro.modoColeta = modoColetarAnterior;
13826
+ for (const h of escopo.antesDeTodos) {
13827
+ await h.chamar(interpretador, [], null);
13828
+ }
13829
+ for (const item of escopo.itensColetados) {
13830
+ if (escopo.temApenas && !item.apenas)
13831
+ continue;
13832
+ if (item.pular) {
13833
+ if (item.tipo === 'teste') {
13834
+ registro.resultados.push({
13835
+ nomeSuite: registro.suiteAtual,
13836
+ nomeTeste: item.nome,
13837
+ status: 'pulado',
13838
+ tempoMs: 0,
13839
+ });
13840
+ }
13841
+ continue;
13842
+ }
13843
+ if (item.tipo === 'teste') {
13844
+ await executarTeste(item.nome, item.fn);
13845
+ }
13846
+ else {
13847
+ await executarGrupo(item.nome, item.fn);
13848
+ }
13849
+ }
13850
+ for (const h of escopo.depoisDeTodos) {
13851
+ await h.chamar(interpretador, [], null);
13852
+ }
13853
+ }
13854
+ finally {
13855
+ registro.pilhaEscopos.pop();
13856
+ registro.modoColeta = modoColetarAnterior;
13857
+ registro.suiteAtual = suiteAnterior;
13806
13858
  interpretador.emDeclaracaoTente = emDeclaracaoTenteAnterior;
13807
13859
  }
13860
+ }
13861
+ function coletarOuExecutar(tipo, nome, fn, pular, apenas) {
13862
+ if (registro.modoColeta && registro.pilhaEscopos.length > 0) {
13863
+ const escopoAtual = registro.pilhaEscopos[registro.pilhaEscopos.length - 1];
13864
+ if (apenas)
13865
+ escopoAtual.temApenas = true;
13866
+ escopoAtual.itensColetados.push({ tipo, nome, fn, pular, apenas });
13867
+ return Promise.resolve();
13868
+ }
13869
+ if (pular) {
13870
+ if (tipo === 'teste') {
13871
+ registro.resultados.push({
13872
+ nomeSuite: registro.suiteAtual,
13873
+ nomeTeste: nome,
13874
+ status: 'pulado',
13875
+ tempoMs: 0,
13876
+ });
13877
+ }
13878
+ return Promise.resolve();
13879
+ }
13880
+ return tipo === 'teste' ? executarTeste(nome, fn) : executarGrupo(nome, fn);
13881
+ }
13882
+ const grupoFn = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13883
+ const nome = interpretador.resolverValor(nomeRaw);
13884
+ const fn = interpretador.resolverValor(funcaoRaw);
13885
+ return coletarOuExecutar('grupo', nome, fn, false, false);
13886
+ });
13887
+ grupoFn['pular'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13888
+ const nome = interpretador.resolverValor(nomeRaw);
13889
+ const fn = interpretador.resolverValor(funcaoRaw);
13890
+ return coletarOuExecutar('grupo', nome, fn, true, false);
13891
+ });
13892
+ grupoFn['apenas'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13893
+ const nome = interpretador.resolverValor(nomeRaw);
13894
+ const fn = interpretador.resolverValor(funcaoRaw);
13895
+ return coletarOuExecutar('grupo', nome, fn, false, true);
13808
13896
  });
13897
+ modulo.componentes['grupo'] = grupoFn;
13898
+ const testeFn = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13899
+ const nome = interpretador.resolverValor(nomeRaw);
13900
+ const fn = interpretador.resolverValor(funcaoRaw);
13901
+ return coletarOuExecutar('teste', nome, fn, false, false);
13902
+ });
13903
+ testeFn['pular'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13904
+ const nome = interpretador.resolverValor(nomeRaw);
13905
+ const fn = interpretador.resolverValor(funcaoRaw);
13906
+ return coletarOuExecutar('teste', nome, fn, true, false);
13907
+ });
13908
+ testeFn['apenas'] = new funcao_padrao_1.FuncaoPadrao(2, async function (_visitante, nomeRaw, funcaoRaw) {
13909
+ const nome = interpretador.resolverValor(nomeRaw);
13910
+ const fn = interpretador.resolverValor(funcaoRaw);
13911
+ return coletarOuExecutar('teste', nome, fn, false, true);
13912
+ });
13913
+ modulo.componentes['teste'] = testeFn;
13914
+ function registrarHook(campo) {
13915
+ return new funcao_padrao_1.FuncaoPadrao(1, function (_visitante, funcaoRaw) {
13916
+ const fn = interpretador.resolverValor(funcaoRaw);
13917
+ if (registro.pilhaEscopos.length > 0) {
13918
+ registro.pilhaEscopos[registro.pilhaEscopos.length - 1][campo].push(fn);
13919
+ }
13920
+ return Promise.resolve(null);
13921
+ });
13922
+ }
13923
+ modulo.componentes['antesDeCada'] = registrarHook('antesDeCada');
13924
+ modulo.componentes['antesDeTodos'] = registrarHook('antesDeTodos');
13925
+ modulo.componentes['depoisDeCada'] = registrarHook('depoisDeCada');
13926
+ modulo.componentes['depoisDeTodos'] = registrarHook('depoisDeTodos');
13809
13927
  modulo.componentes['lancarErro'] = new funcao_padrao_1.FuncaoPadrao(1, function (_visitante, mensagemRaw) {
13810
13928
  const mensagem = interpretador.resolverValor(mensagemRaw);
13811
13929
  return Promise.reject(new erro_de_assertiva_1.ErroDeAssertiva(simboloAtual(interpretador), String(mensagem)));
@@ -13821,6 +13939,8 @@ class RegistroTestes {
13821
13939
  constructor() {
13822
13940
  this.resultados = [];
13823
13941
  this.suiteAtual = '';
13942
+ this.pilhaEscopos = [];
13943
+ this.modoColeta = false;
13824
13944
  }
13825
13945
  }
13826
13946
  exports.RegistroTestes = RegistroTestes;
@@ -21914,7 +22034,7 @@ class InterpretadorBase {
21914
22034
  */
21915
22035
  async visitarExpressaoAgrupamento(expressao) {
21916
22036
  const avaliacaoAgrupamento = await this.avaliar(expressao.expressao);
21917
- if (avaliacaoAgrupamento.declaracao !== undefined) {
22037
+ if (avaliacaoAgrupamento !== null && avaliacaoAgrupamento.declaracao) {
21918
22038
  return avaliacaoAgrupamento.declaracao;
21919
22039
  }
21920
22040
  return avaliacaoAgrupamento;
@@ -22172,12 +22292,12 @@ class InterpretadorBase {
22172
22292
  this.tiposNumericos.includes(tipoDireito)) {
22173
22293
  return Number(valorEsquerdo) + Number(valorDireito);
22174
22294
  }
22295
+ if (valorEsquerdo === null || valorDireito === null) {
22296
+ return this.paraTexto(valorEsquerdo) + this.paraTexto(valorDireito);
22297
+ }
22175
22298
  // TODO: Se tipo for 'qualquer', seria uma boa confiar nos operadores
22176
22299
  // tradicionais do JavaScript?
22177
- if (tipoEsquerdo === 'qualquer' ||
22178
- tipoDireito === 'qualquer' ||
22179
- tipoEsquerdo === 'nulo' ||
22180
- tipoDireito === 'nulo') {
22300
+ if (tipoEsquerdo === 'qualquer' || tipoDireito === 'qualquer') {
22181
22301
  return valorEsquerdo + valorDireito;
22182
22302
  }
22183
22303
  return this.paraTexto(valorEsquerdo) + this.paraTexto(valorDireito);
@@ -22733,35 +22853,22 @@ class InterpretadorBase {
22733
22853
  return retornoExecucao;
22734
22854
  }
22735
22855
  async visitarDeclaracaoEscolha(declaracao) {
22736
- const condicaoEscolha = await this.avaliar(declaracao.identificadorOuLiteral);
22737
- const valorCondicaoEscolha = this.resolverValor(condicaoEscolha);
22738
- const caminhos = declaracao.caminhos;
22739
- const caminhoPadrao = declaracao.caminhoPadrao;
22740
- let encontrado = false;
22741
22856
  try {
22742
- for (let i = 0; i < caminhos.length; i++) {
22743
- const caminho = caminhos[i];
22744
- for (let j = 0; j < caminho.condicoes.length; j++) {
22745
- const condicaoAvaliada = await this.avaliar(caminho.condicoes[j]);
22857
+ const condicaoEscolha = await this.avaliar(declaracao.identificadorOuLiteral);
22858
+ const valorCondicaoEscolha = this.resolverValor(condicaoEscolha);
22859
+ const caminhos = declaracao.caminhos;
22860
+ const caminhoPadrao = declaracao.caminhoPadrao;
22861
+ for (const caminho of caminhos) {
22862
+ for (const condicao of caminho.condicoes) {
22863
+ const condicaoAvaliada = await this.avaliar(condicao);
22746
22864
  if (condicaoAvaliada === valorCondicaoEscolha) {
22747
- encontrado = true;
22748
- try {
22749
- await this.executarBloco(caminho.declaracoes);
22750
- }
22751
- catch (erro) {
22752
- this.erros.push({
22753
- erroInterno: erro,
22754
- linha: declaracao.linha,
22755
- hashArquivo: declaracao.hashArquivo,
22756
- });
22757
- return Promise.reject(erro);
22758
- }
22865
+ return await this.executarBloco(caminho.declaracoes);
22759
22866
  }
22760
22867
  }
22761
22868
  }
22762
- if (caminhoPadrao !== null && !encontrado) {
22869
+ if (caminhoPadrao !== null) {
22763
22870
  this.registrarRamo?.(declaracao.hashArquivo, declaracao.linha, 'caso-padrao');
22764
- await this.executarBloco(caminhoPadrao.declaracoes);
22871
+ return await this.executarBloco(caminhoPadrao.declaracoes);
22765
22872
  }
22766
22873
  }
22767
22874
  catch (erro) {
@@ -24488,6 +24595,9 @@ class Interpretador extends interpretador_base_1.InterpretadorBase {
24488
24595
  variavelObjeto = variavelObjeto.valor;
24489
24596
  }
24490
24597
  const objeto = this.resolverValor(variavelObjeto);
24598
+ if (objeto === null || objeto === undefined) {
24599
+ return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(undefined, `Não é possível acessar a propriedade '${expressao.nomeMetodo}' de um valor nulo.`, expressao.linha));
24600
+ }
24491
24601
  if (objeto.constructor && objeto.constructor === estruturas_1.ObjetoDeleguaClasse) {
24492
24602
  try {
24493
24603
  return objeto.obterMetodo(expressao.nomeMetodo);
@@ -24623,6 +24733,9 @@ class Interpretador extends interpretador_base_1.InterpretadorBase {
24623
24733
  variavelObjeto = retornoQuebra.valor;
24624
24734
  }
24625
24735
  const objeto = this.resolverValor(variavelObjeto, true);
24736
+ if (objeto === null || objeto === undefined) {
24737
+ return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(undefined, `Não é possível acessar a propriedade '${expressao.simbolo.lexema}' de um valor nulo.`, expressao.linha));
24738
+ }
24626
24739
  // Acesso a método via `super()`: percorre o OReM a partir de `proximaClasse`,
24627
24740
  // vincula o método encontrado à instância original e registra `classeDefinidora`
24628
24741
  // para que chamadas aninhadas a `super()` avancem corretamente na cadeia.
@@ -24792,12 +24905,14 @@ class Interpretador extends interpretador_base_1.InterpretadorBase {
24792
24905
  // Por exemplo, `objeto1.metodo1().metodo2()`.
24793
24906
  // Como `RetornoQuebra` também possui `valor`, precisamos extrair o
24794
24907
  // valor dele primeiro.
24795
- if (variavelObjeto.constructor === quebras_1.RetornoQuebra) {
24908
+ if (variavelObjeto && variavelObjeto.constructor === quebras_1.RetornoQuebra) {
24796
24909
  variavelObjeto = variavelObjeto.valor;
24797
24910
  }
24798
24911
  const objeto = this.resolverValor(variavelObjeto);
24799
- // Outro caso que `instanceof` simplesmente não funciona para casos em Liquido,
24800
- // então testamos também o nome do construtor.
24912
+ if (objeto === null || objeto === undefined) {
24913
+ return Promise.reject(new excecoes_1.ErroEmTempoDeExecucao(undefined, `Não é possível acessar a propriedade '${expressao.nomePropriedade}' de um valor nulo.`, expressao.linha));
24914
+ }
24915
+ // A partir daqui, o interpretador sabe que 'objeto' não é nulo.
24801
24916
  if (objeto.constructor === estruturas_1.ObjetoDeleguaClasse) {
24802
24917
  return objeto.obterMetodo(expressao.nomePropriedade) || null;
24803
24918
  }