Skip to content

feat: recursos do debugger (call stack, data breakpoints, erros de runtime, inspeção de arrays/strings) - #17

Merged
NullSablex merged 34 commits into
masterfrom
feat/recursos-faltantes
Sep 1, 2026
Merged

feat: recursos do debugger (call stack, data breakpoints, erros de runtime, inspeção de arrays/strings)#17
NullSablex merged 34 commits into
masterfrom
feat/recursos-faltantes

Conversation

@NullSablex

@NullSablex NullSablex commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Recursos do debugger acumulados nesta branch, um commit por recurso concluído. Todos validados; docs alinhadas.

Base / dependência

  • chore: re-pin rust-samp SDK no master estável do fork (inclui Amx::hlw, PR do fork #54 mergeado).
  • Pendente: mergear o PR #55 do fork (function_address) para re-pinar num commit estável do master. É o único bloqueio para este PR fechar com pin definitivo.

Recursos

  • Call stack multi-frame — caminha os frames do AMX; função, linha e variáveis por frame.
  • Data breakpoints — pausa quando um valor muda: globais, locais e elementos de array; watches de locais expiram ao retornar o frame.
  • Mais erros de runtime — STACKERR / HEAPLOW / MEMACCESS, fiéis ao amx.c, conservadores.
  • Inspeção rica de arrays/strings — arrays expansíveis (elementos como filhos) e arrays de char como string.
  • Breakpoints de função — parar ao entrar numa função pelo nome; união com os breakpoints de linha num só conjunto no plugin.
  • Autocomplete (completions) e filtro de exceção no painel de breakpoints.
  • setExpression — editar lvalue (arr[i] = 10) no watch/console, com índice por subexpressão.
  • readMemory — hex view da memória de dados crua; variáveis expõem memoryReference e o adaptador devolve base64 (encoder próprio, sem dependência nova).

Protocolo

Command::ReadMemoryEvent::MemoryData é o primeiro canal request/response do protocolo: correlacionado por id sequencial, com timeout, para a sessão nunca ficar presa se o plugin não responder. O resto continua assíncrono nos dois sentidos.

Validação

  • 94 testes (unidade), clippy pedantic, fmt, aarch64 — verdes.
  • Fluxos exercitados ao vivo num servidor SA-MP real (call stack, data breakpoints, os 3 erros de runtime) nos compiladores 3.10.10 e 3.10.11.
  • Verificação por cliente DAP no terminal confirmou os dados corretos no fio (inclusive descartando um falso-alarme que era do harness de teste — ver issue Reiniciar/Continuar: snapshot inconsistente / dados defasados (pré-existente) #18, fechada).
  • Site da documentação: mkdocs build --strict num venv limpo, instalando com pip install --require-hashes.

Docs e repositório

  • README reescrito: badges (CI, CodeQL, docs, scorecard, release, downloads, stars, licença), navegação e tabela de recursos alinhada ao que a branch entrega.
  • docs/features.md, docs/architecture.md, docs/index.md, docs/getting-started.md e docs/runtime-errors.md atualizados; CHANGELOG.md com a seção Não lançado.
  • Site bilínguemkdocs-static-i18n com pt-BR na raiz e en-US em /en-US/, as seis páginas traduzidas e o nav via nav_translations. O tema do locale en-US aponta para en porque o Material não tem tabela de interface para en-US.
  • Novo workflow scorecard.yml (OpenSSF Scorecard): sem ele o badge de scorecard não tem o que exibir, porque a API pública só conhece repositórios que publicam resultados. O badge passa a funcionar após a primeira execução no master.
  • Limpeza de comentárioshook.rs estava inteiramente em inglês e foi traduzido (mais pontos isolados em plugin_client.rs, inspect.rs e langs/en.rs); cortado o que repetia a assinatura, e corrigido um doc-comment que ainda dizia que arrays não eram observáveis.

The CodeQL default setup only analysed a pull request when it touched
files relevant to the configured languages, so a docs-only PR produced
no analysis while master still carried one per language, leaving the
code_scanning branch rule unable to diff the two sides.

Also add the CODEOWNERS file this repository was missing, so the branch
ruleset can require code owner review like the sibling repositories do.
Traz o lookup_function do bloco de debug (base para a pilha de chamadas),
Amx::exec_public_scope e o hardening de buffer/stack no FFI. Eventos do SDK
(#[event]) são x86-only e viram no-op no check aarch64.
Caminha a cadeia de frames do AMX (FRM anterior + endereço de retorno,
parando no público de entrada) e expõe N frames ao editor. Cada frame traz
nome da função (lookup_function), linha e variáveis em escopo — reaproveitando
inspect::collect por frame.

- protocolo: Event::Paused passa a carregar frames: Vec<Frame>; Command::
  SetVariable ganha o índice do frame.
- plugin: novo módulo stack (walker puro e testável) + build_frames no on_pause;
  PAUSE_CTX guarda o contexto de todos os frames para editar no frame certo.
- adaptador: stackTrace com N frames + source; scopes/variables/evaluate/
  setVariable operam por frame (frameId/variablesReference).

Cobertura: 6 testes do walker + 2 do plumbing do adaptador. aarch64 ok.
Observa variáveis (globais e locais) e pausa na primeira linha após o valor
mudar. Reusa o hook por linha; watches de locais expiram quando o frame dono
retorna (via stack::walk), evitando observar slot de pilha reusado.

- protocolo: Command::SetDataBreakpoints { watches: Vec<DataWatch{frame,name}> }.
- plugin: control::DataWatch + check_data_watches (puro, com expiração por frame
  vivo); hook resolve frame+nome → endereço/classe/valor inicial e checa a cada
  linha, pausando com reason "data breakpoint".
- adaptador: capability supportsDataBreakpoints; dataBreakpointInfo (dataId
  "frame:name") e setDataBreakpoints encaminhando ao plugin.

Cobertura: 5 testes do controlador (mudança/expiração/global) + 3 do adaptador
(parse_data_id, encaminhamento, capability). aarch64 ok.
Traz o accessor hlw() (fundo do heap) necessário para detectar heap underflow.
Aponta para a branch do PR NullSablex/rust-samp#54; re-pinar no master estável
quando o PR mergear, antes de fechar este.
Estende o simulador de linha (runtime_error) para rastrear stk/hea/hlw/stp e
detectar, antes do abort da VM e com as MESMAS condições do amx.c:
- STACKERR: colisão pilha/heap (CHKMARGIN, hea+STKMARGIN>stk), inclusive
  antecipando o PROC do chamado num call (recursão infinita).
- HEAPLOW: underflow de heap (CHKHEAP, hea<hlw).
- MEMACCESS: endereço na lacuna [hea,stk) ou >=stp (VERIFYADDRESS).

Conservador por construção: as checagens só rodam enquanto stk/hea (e o
registrador de endereço) são rastreados exatamente; qualquer desvio/opcode não
modelado (call, jump, sysreq, sctrl, aritmética) as desliga — nunca um
falso-positivo. Números de opcode e condições conferidos no amx.c do
omp-compiler. Mensagens localizadas nos 5 idiomas.

Cobertura: +6 testes (colisão em stack/call, heaplow, memaccess na lacuna,
endereço desconhecido não acusa, barreira pós-call). aarch64 ok.
O PR NullSablex/rust-samp#54 (Amx::hlw) foi mergeado; sai da branch do PR e
aponta para o master estável do fork.
@NullSablex
NullSablex marked this pull request as ready for review August 31, 2026 08:19
…cluídos

Alinha docs/features.md e docs/runtime-errors.md ao que o PR entrega (estavam
como 'planejado'/'em avaliação'). Adiciona STACKERR/HEAPLOW/MEMACCESS à tabela
de erros com as condições fiéis ao amx.c.
Arrays viram expansíveis na árvore de variáveis (elementos como filhos com
variablesReference próprio) e arrays de char são mostrados como string; editar
um elemento (arr[i]) passa a ser suportado.

- protocolo: Var ganha children (elementos); Command::SetVariable ganha index
  opcional (elemento do array).
- plugin: inspect::build_array lê os elementos (até 256) e detecta string
  (imprimível até terminador 0, Latin-1); hook::set_variable escreve arr[index].
- adaptador: variablesReference codifica (frame, var) para expandir arrays e
  editar elementos; dataBreakpointInfo passa a recusar arrays por terem filhos.

Cobertura: as_string (detecção/conservadorismo), encode/decode de ref de array,
parse de índice. 77 testes; clippy pedantic, fmt, aarch64 ok.
@NullSablex NullSablex changed the title feat: recursos faltantes do debugger (call stack, data breakpoints, mais erros de runtime) feat: recursos do debugger (call stack, data breakpoints, erros de runtime, inspeção de arrays/strings) Aug 31, 2026
evaluate passa a avaliar expressões, não só o nome exato: literais, variáveis,
elementos de array (arr[i], índice pode ser subexpressão) e A OP B com
+ - * / % (aritmética inteira estilo Pawn, ou float) e == != < > <= >=
(comparação). Um operador por expressão, conservador — o que não avalia vira
falha (o editor mostra 'não disponível').

Novo módulo expr no adaptador, puro e testável (11 testes).
O editor passa a controlar a pausa em erros de runtime via exceptionBreakpoint
Filters/setExceptionBreakpoints. Desligado, a VM aborta normalmente sem pausar.

- protocolo: Command::SetExceptionFilter { runtime }.
- plugin: flag atômica RUNTIME_ERRORS (ligada por padrão) que porteia o
  detect_runtime_error no on_break.
- adaptador: capability exceptionBreakpointFilters + handler setExceptionBreakpoints.

Cobertura: encaminhamento liga/desliga + capability. 85 testes.
Traz function_address (nome->endereço de entrada) para os breakpoints de função.
Aponta para a branch do PR NullSablex/rust-samp#55; re-pinar no master quando
mergear, antes de fechar este.
setFunctionBreakpoints resolve cada nome no endereço de entrada da função
(AmxDbg::function_address) e o une aos breakpoints de linha no conjunto único
do plugin. Capability supportsFunctionBreakpoints. Útil para callbacks
(OnPlayerConnect etc.) sem procurar a linha.

Cobertura: resolução + união linha/função + capability. 87 testes.
As mensagens voltadas ao editor (valor/elemento inválido, editar array,
expressão vazia/não avaliável, rótulo do filtro de exceção) passam a seguir o
idioma — antes eram só pt-BR, enquanto os erros de runtime já eram localizados.
O locale vem do argumento 'locale' do initialize (o cliente informa).

Novo módulo l10n (Locale + Msg) espelhando pt-BR/en/es/ru/ro. 89 testes.
Responde ao completions do DAP sugerindo as variáveis em escopo cujo nome
começa com o identificador antes do cursor. Capability supportsCompletionsRequest.

Cobertura: word_prefix (extração do prefixo). 90 testes.
Unifica a localização num só lugar (crates/protocol/src/messages), com Locale,
MsgKey (11 chaves) e um módulo por idioma em langs/<code>.rs (get -> &str,
templates com {}). Plugin e adaptador passam a usar essa fonte única:
- plugin: runtime_error re-exporta o Locale e delega message() a messages::msg.
- adaptador: remove l10n.rs; usa messages::format/msg (from_tag no initialize).

O match por MsgKey em cada idioma é exaustivo — falta chave = não compila.
Cobertura documentada em docs/i18n.md (en, pt-BR, es, ru, ro: 11/11). 90 testes.
Espelha a meta de cobertura: 5 implementados (✅) e 45 no roadmap (⬜). Adiciona
a página de localização ao nav do mkdocs.
Arrays deixam de ser inobserváveis: dá para observar arr[i]. dataBreakpointInfo
oferece o elemento (dataId frame:name:index) quando o variablesReference é de um
array; o plugin resolve o endereço do elemento (base + index*4) e observa.

- protocolo: DataWatch ganha index opcional.
- adaptador: dataBreakpointInfo/parse_data_id tratam o índice.
- plugin: resolve_data_watches lê o elemento e nomeia o watch 'arr[i]'.

90 testes; clippy pedantic, fmt, aarch64 ok.
Edita um lvalue (name ou arr[i], índice podendo ser subexpressão) digitado no
watch/console, encaminhando como SetVariable ao plugin. Capability
supportsSetExpression.

Cobertura: parse_lvalue + encaminhamento de elemento. 92 testes; aarch64 ok.
Adiciona um canal request/response ao protocolo (Command::ReadMemory ↔
Event::MemoryData, correlacionados por id) — o primeiro caminho em que o plugin
responde a uma consulta. Variáveis expõem memoryReference (frame:name[:index]);
o plugin resolve o endereço e lê count bytes; o adaptador responde em base64.

- protocolo: ReadMemory/MemoryData.
- plugin: hook::read_memory (resolve endereço, lê cells, responde via evento).
- adaptador: plugin_client.read_memory (envia e espera com timeout, via canal);
  variables com memoryReference; on_read_memory + Outgoing::ReadMemory resolvido
  no main (base64_encode próprio, sem dependência). Capability
  supportsReadMemoryRequest.

Cobertura: base64 (RFC), parse do memoryReference. 94 testes; aarch64 ok.
O bloco de capabilities do initialize tinha um comentário por flag, traduzindo
o nome dela. Mantidos só os que carregam informação não-óbvia (filtro de exceção
e o motivo de não declarar supportsRestartRequest).

Traduz também o único comentário em inglês do plugin, no hook.
README com badges (CI, CodeQL, docs, release, licença), navegação para a
documentação e tabela de recursos alinhada ao que a branch entrega.

docs/features.md ganha as seções de breakpoints de função, expressões do
watch/console, data breakpoints e leitura de memória; architecture.md descreve o
canal request/response (ReadMemory/MemoryData); index.md e getting-started.md
atualizados; CHANGELOG com a seção Não lançado.
hook.rs estava inteiramente comentado em inglês, destoando do resto do repo;
plugin_client.rs, inspect.rs e langs/en.rs tinham pontos isolados. Todos
traduzidos.

Na passagem, corta o que repetia a assinatura ou já estava dito noutro lugar: as
notas '&mut self porque...' no control.rs, a lista de parâmetros no doc de
scan_line e a terceira repetição do argumento conservador.

Corrige também o doc de resolve_data_watches, que ainda dizia que arrays não são
observáveis — elementos de array passaram a ser em ed5a737.
A tabela omitia OP_CALL_PRI no STACKERR e OP_LODB_I/OP_STRB_I/OP_LIDX_B no
MEMACCESS, todos checados em runtime_error.rs.
Adiciona também .github/workflows/scorecard.yml: sem ele o badge do Scorecard
não tem o que exibir, porque a API pública do OpenSSF só conhece repositórios
que publicam resultados (publish_results, em push no branch padrão).

O workflow segue o padrão dos outros: actions pinadas por SHA, permissões
mínimas por job e execução semanal além do push no master. O SARIF também vai
para o code scanning.
Adiciona o plugin mkdocs-static-i18n (docs_structure: suffix), com pt-BR como
idioma padrão na raiz e en-US em /en-US/. As seis páginas foram traduzidas, e o
nav tem nav_translations; fallback_to_default cobre páginas futuras que ainda não
tenham versão traduzida.

O tema do locale en-US aponta para 'en': o Material só traz tabela de interface
para 'en', e 'en-US' quebra o build (TemplateNotFound em
partials/languages/en-US.html).

requirements.in/txt recompilados com hashes. Validado como no CI: venv limpo,
pip install --require-hashes e mkdocs build --strict.
A seção Não lançado parou nos recursos; faltavam o README com badges, o site
bilíngue, a padronização dos comentários, as duas correções de documentação e o
workflow do OpenSSF Scorecard.
Fecha o ciclo desde a v0.1.0: call stack multi-frame, data breakpoints,
breakpoints de função, três novos erros de runtime, inspeção de arrays/strings,
setExpression, readMemory, expressões no watch, autocomplete e a documentação em
inglês.

Sobe a versão do workspace e o marcador embutido no plugin (a extensão casa
apenas o prefixo PAWNPRO_DEBUG_MARKER, então a versão dentro dele é livre; o
tamanho segue 26 bytes).

O changelog passa a cobrir todas as mudanças desde o último release, incluindo os
re-pins do SDK e a infraestrutura do repositório.
@NullSablex NullSablex added enhancement New feature or request documentation Improvements or additions to documentation labels Sep 1, 2026
A numeração de opcodes, o tamanho das instruções, o OpcodeMap, a caminhada da
pilha e a leitura de faixa de memória eram fatos genéricos da VM AMX que viviam
no plugin. Passaram para o SDK e voltam como API:

- samp::debug::opcode substitui as 44 constantes locais, a tabela OP_PARAMS e
  STK_MARGIN; operand_cells troca o índice cru por uma consulta checada.
- samp::debug::stack substitui crates/debug-plugin/src/stack.rs, removido com
  seus 6 testes (reescritos no SDK).
- Amx::read_bytes substitui o alinhamento e o fatiamento manuais do readMemory.
- Amx::data_only substitui Amx::new(ptr, 0) nos três pontos da pausa.
- Amx::opcode_map substitui OpcodeMap::new(amx.opcode_table(OP_NUM_OPCODES)).

O plugin perde ~250 linhas sem mudança de comportamento: 88 testes (os 6 que
saíram vivem agora no SDK), clippy pedantic e fmt verdes.
A dependência git + rev existia porque o debugger precisava de API do SDK que
ainda não estava publicada. Com o lançamento da 3.4.0 (rust-samp e
rust-samp-sdk), passa a ser dependência de versão: acaba o re-pin por SHA a
cada mudança no SDK e o build deixa de resolver nada pelo GitHub — não há mais
nenhuma dependência git no Cargo.lock.
Faltavam a fileira de badges do README, o marcador do plugin subindo para
0.2.0, a correção da tabela de opcodes em runtime-errors.md e as atualizações
de dependência do Dependabot nos três ecossistemas.

Conferido item a item contra os 50 commits desde a tag.
@NullSablex
NullSablex merged commit 7f3cc1e into master Sep 1, 2026
5 checks passed
@NullSablex
NullSablex deleted the feat/recursos-faltantes branch September 1, 2026 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant