change comments to English

This commit is contained in:
bQUARKz 2026-02-05 23:20:56 +00:00
parent 66f34eeb58
commit 912b9b0075
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
8 changed files with 61 additions and 62 deletions

View File

@ -1,10 +1,10 @@
/// TextIndex fornece conversões entre offsets em bytes (usados no core) /// TextIndex provides conversions between byte offsets (used in the core)
/// e posições LSP (linha, coluna em unidades UTF-16). /// and LSP positions (line, column in UTF-16 units).
/// ///
/// Observações: /// Notes:
/// - `line_starts` guarda os offsets em bytes do início de cada linha. /// - `line_starts` stores byte offsets for the start of each line.
/// - Mantemos uma cópia do texto para permitir conversões sem dependências externas. /// - We keep a copy of the text to allow conversions without external dependencies.
/// - A coluna LSP é contada em unidades UTF-16, excluindo o `\n` do fim de linha. /// - The LSP column is counted in UTF-16 units, excluding the end-of-line `\n`.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TextIndex { pub struct TextIndex {
text: String, text: String,
@ -12,13 +12,13 @@ pub struct TextIndex {
} }
impl TextIndex { impl TextIndex {
/// Constrói o índice a partir do conteúdo textual atual do arquivo. /// Builds the index from the file's current textual content.
pub fn new(text: &str) -> Self { pub fn new(text: &str) -> Self {
let mut line_starts = Vec::with_capacity(128); let mut line_starts = Vec::with_capacity(128);
line_starts.push(0); line_starts.push(0);
for (byte, ch) in text.char_indices() { for (byte, ch) in text.char_indices() {
if ch == '\n' { if ch == '\n' {
// início da próxima linha é o byte após o '\n' // the start of the next line is the byte after the '\n'
line_starts.push((byte + 1) as u32); line_starts.push((byte + 1) as u32);
} }
} }
@ -28,15 +28,15 @@ impl TextIndex {
} }
} }
/// Número de linhas (0-based; linhas vazias contam). /// Number of lines (0-based; empty lines count).
#[inline] #[inline]
pub fn line_count(&self) -> u32 { pub fn line_count(&self) -> u32 {
self.line_starts.len() as u32 self.line_starts.len() as u32
} }
/// Converte um offset em bytes (dentro do arquivo) para (linha, coluna UTF-16) no padrão LSP. /// Converts a byte offset (within the file) to (line, UTF-16 column) in LSP format.
/// ///
/// Para offsets exatamente no fim da linha, a coluna será o comprimento UTF-16 da linha. /// For offsets exactly at end-of-line, the column will be the line's UTF-16 length.
pub fn byte_to_lsp(&self, byte: u32) -> (u32, u32) { pub fn byte_to_lsp(&self, byte: u32) -> (u32, u32) {
let byte = byte.min(self.text.len() as u32); let byte = byte.min(self.text.len() as u32);
let line = match self.line_starts.binary_search(&byte) { let line = match self.line_starts.binary_search(&byte) {
@ -56,10 +56,10 @@ impl TextIndex {
(line, utf16_col) (line, utf16_col)
} }
/// Converte (linha, coluna UTF-16) em offset em bytes. /// Converts (line, UTF-16 column) to a byte offset.
/// ///
/// - Linhas fora do intervalo são clampadas para [0, last]. /// - Lines outside the range are clamped to [0, last].
/// - Colunas maiores que o tamanho UTF-16 da linha retornam o fim da linha. /// - Columns larger than the line's UTF-16 length return end-of-line.
pub fn lsp_to_byte(&self, line: u32, utf16_col: u32) -> u32 { pub fn lsp_to_byte(&self, line: u32, utf16_col: u32) -> u32 {
let line = line.min(self.line_count().saturating_sub(1)); let line = line.min(self.line_count().saturating_sub(1));
let (line_start, line_end) = self.line_bounds(line); let (line_start, line_end) = self.line_bounds(line);
@ -72,7 +72,7 @@ impl TextIndex {
} }
acc += ch.len_utf16() as u32; acc += ch.len_utf16() as u32;
} }
// Se a coluna alvo é após o último caractere, retorne o fim da linha. // If the target column is after the last character, return end-of-line.
line_end as u32 line_end as u32
} }
@ -83,9 +83,8 @@ impl TextIndex {
.get(line as usize) .get(line as usize)
.unwrap_or(self.line_starts.last().unwrap()); .unwrap_or(self.line_starts.last().unwrap());
let next = self.line_starts.get(line as usize + 1).copied(); let next = self.line_starts.get(line as usize + 1).copied();
// Se existe próxima linha, `next` aponta para o byte após o '\n' da linha atual // If there is a next line, `next` points to the byte after the current line's '\n',
// então o conteúdo termina em `next - 1`. Caso contrário (última linha), // so the content ends at `next - 1`. Otherwise (last line), the content ends at `text.len()`.
// o conteúdo termina em `text.len()`.
let end = match next { let end = match next {
Some(next_start) => next_start.saturating_sub(1), Some(next_start) => next_start.saturating_sub(1),
None => self.text.len() as u32, None => self.text.len() as u32,
@ -103,11 +102,11 @@ mod tests_internal {
let s = "ab\ncd\n"; let s = "ab\ncd\n";
let idx = TextIndex::new(s); let idx = TextIndex::new(s);
assert_eq!(idx.line_count(), 3); assert_eq!(idx.line_count(), 3);
// linha 0: "ab" // line 0: "ab"
assert_eq!(idx.line_bounds(0), (0, 2)); assert_eq!(idx.line_bounds(0), (0, 2));
// linha 1: "cd" // line 1: "cd"
assert_eq!(idx.line_bounds(1), (3, 5)); assert_eq!(idx.line_bounds(1), (3, 5));
// linha 2: linha vazia final // line 2: final empty line
assert_eq!(idx.line_bounds(2), (6, 6)); assert_eq!(idx.line_bounds(2), (6, 6));
} }
} }

View File

@ -5,22 +5,22 @@ fn text_index_ascii_roundtrip() {
let text = "hello\nworld\nthis is ascii"; let text = "hello\nworld\nthis is ascii";
let idx = TextIndex::new(text); let idx = TextIndex::new(text);
// Verifica round-trip em todas as fronteiras de char // Verify round-trip on all character boundaries
let mut boundaries: Vec<usize> = text.char_indices().map(|(i, _)| i).collect(); let mut boundaries: Vec<usize> = text.char_indices().map(|(i, _)| i).collect();
boundaries.push(text.len()); boundaries.push(text.len());
for &b in &boundaries { for &b in &boundaries {
let (line, col16) = idx.byte_to_lsp(b as u32); let (line, col16) = idx.byte_to_lsp(b as u32);
let b2 = idx.lsp_to_byte(line, col16); let b2 = idx.lsp_to_byte(line, col16);
assert_eq!(b2, b as u32, "roundtrip falhou para byte {} -> (l={},c16={})", b, line, col16); assert_eq!(b2, b as u32, "roundtrip failed for byte {} -> (l={},c16={})", b, line, col16);
} }
// Alguns checks diretos // Some direct checks
// início: (0,0) // start: (0,0)
assert_eq!(idx.byte_to_lsp(0), (0, 0)); assert_eq!(idx.byte_to_lsp(0), (0, 0));
// após "hello" (5), antes do '\n': linha 0, col=5 // after "hello" (5), before '\n': line 0, col=5
assert_eq!(idx.byte_to_lsp(5), (0, 5)); assert_eq!(idx.byte_to_lsp(5), (0, 5));
// após '\n' (6): linha 1, col=0 // after '\n' (6): line 1, col=0
assert_eq!(idx.byte_to_lsp(6), (1, 0)); assert_eq!(idx.byte_to_lsp(6), (1, 0));
} }
@ -30,25 +30,25 @@ fn text_index_unicode_roundtrip_utf16() {
let text = "aé🙂b"; let text = "aé🙂b";
let idx = TextIndex::new(text); let idx = TextIndex::new(text);
// fronteiras de char + fim // character boundaries + end
let mut boundaries: Vec<usize> = text.char_indices().map(|(i, _)| i).collect(); let mut boundaries: Vec<usize> = text.char_indices().map(|(i, _)| i).collect();
boundaries.push(text.len()); boundaries.push(text.len());
for &b in &boundaries { for &b in &boundaries {
let (line, col16) = idx.byte_to_lsp(b as u32); let (line, col16) = idx.byte_to_lsp(b as u32);
let b2 = idx.lsp_to_byte(line, col16); let b2 = idx.lsp_to_byte(line, col16);
assert_eq!(b2, b as u32, "roundtrip unicode falhou para byte {} -> (l={},c16={})", b, line, col16); assert_eq!(b2, b as u32, "unicode roundtrip failed for byte {} -> (l={},c16={})", b, line, col16);
} }
// Checagens de colunas esperadas na linha 0 // Expected columns on line 0
// bytes: [0:'a'][1..2:'é'][3..6:'🙂'][7:'b'][8:end] // bytes: [0:'a'][1..2:'é'][3..6:'🙂'][7:'b'][8:end]
assert_eq!(idx.byte_to_lsp(0), (0, 0)); // antes de 'a' assert_eq!(idx.byte_to_lsp(0), (0, 0)); // before 'a'
assert_eq!(idx.byte_to_lsp(1), (0, 1)); // após 'a' assert_eq!(idx.byte_to_lsp(1), (0, 1)); // after 'a'
assert_eq!(idx.byte_to_lsp(3), (0, 2)); // após 'a' + 'é' (1+1 utf16) assert_eq!(idx.byte_to_lsp(3), (0, 2)); // after 'a' + 'é' (1+1 utf16)
assert_eq!(idx.byte_to_lsp(7), (0, 4)); // após '🙂' (2 utf16) => 1+1+2=4 assert_eq!(idx.byte_to_lsp(7), (0, 4)); // after '🙂' (2 utf16) => 1+1+2=4
assert_eq!(idx.byte_to_lsp(8), (0, 5)); // após 'b' assert_eq!(idx.byte_to_lsp(8), (0, 5)); // after 'b'
// e inverso, colunas específicas // and inverse, specific columns
assert_eq!(idx.lsp_to_byte(0, 0), 0); assert_eq!(idx.lsp_to_byte(0, 0), 0);
assert_eq!(idx.lsp_to_byte(0, 1), 1); assert_eq!(idx.lsp_to_byte(0, 1), 1);
assert_eq!(idx.lsp_to_byte(0, 2), 3); assert_eq!(idx.lsp_to_byte(0, 2), 3);

View File

@ -113,8 +113,8 @@ impl TypeFacts {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
// Mock de NameId e SymbolId para testes simplificados se necessário, // Mock NameId and SymbolId for simplified tests if necessary,
// ou usar valores reais. // or use real values.
#[test] #[test]
fn type_arena_push_is_append_only() { fn type_arena_push_is_append_only() {
@ -138,7 +138,7 @@ mod tests {
assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. })); assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. }));
assert!(matches!(arena.kind(t2), TypeKind::Optional { .. })); assert!(matches!(arena.kind(t2), TypeKind::Optional { .. }));
// Adicionar mais tipos não deve mudar os anteriores // Adding more types should not change the previous ones
let t3 = arena.intern_type(TypeKind::Array { inner: t1, len: None }); let t3 = arena.intern_type(TypeKind::Array { inner: t1, len: None });
assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. })); assert!(matches!(arena.kind(t1), TypeKind::Primitive { .. }));
assert!(matches!(arena.kind(t2), TypeKind::Optional { .. })); assert!(matches!(arena.kind(t2), TypeKind::Optional { .. }));

View File

@ -225,7 +225,7 @@ fn walk_node(
walk_node(member, arena, module, index, imports, ref_index, node_to_symbol, diagnostics); walk_node(member, arena, module, index, imports, ref_index, node_to_symbol, diagnostics);
} }
} }
// Nós literais ou que não contém outros nós para percorrer (neste nível) // Literal nodes or those that do not contain other nodes to walk (at this level)
NodeKind::IntLit(_) | NodeKind::FloatLit(_) | NodeKind::BoundedLit(_) | NodeKind::StringLit(_) | NodeKind::IntLit(_) | NodeKind::FloatLit(_) | NodeKind::BoundedLit(_) | NodeKind::StringLit(_) |
NodeKind::TypeName(_) | NodeKind::TypeApp(_) | NodeKind::Import(_) | NodeKind::ImportSpec(_) | NodeKind::TypeName(_) | NodeKind::TypeApp(_) | NodeKind::Import(_) | NodeKind::ImportSpec(_) |
NodeKind::ServiceFnSig(_) | NodeKind::ConstructorDecl(_) | NodeKind::ConstantDecl(_) => {} NodeKind::ServiceFnSig(_) | NodeKind::ConstructorDecl(_) | NodeKind::ConstantDecl(_) => {}

View File

@ -441,9 +441,9 @@ impl<'a> Resolver<'a> {
let sym_id = self.define_local(param.name, param.span.clone(), SymbolKind::Local); let sym_id = self.define_local(param.name, param.span.clone(), SymbolKind::Local);
if let (Some(tid), Some(sid)) = (ty_id, sym_id) { if let (Some(tid), Some(sid)) = (ty_id, sym_id) {
self.type_facts.set_symbol_type(sid, tid); self.type_facts.set_symbol_type(sid, tid);
// O node do Ident do parâmetro na declaração também pode ser vinculado // The Ident node of the parameter in the declaration could also be bound
// Mas o ParamNodeArena não tem um NodeId direto no AST que represente o Ident do parâmetro. // But ParamNodeArena does not have a direct NodeId in the AST that represents the parameter's Ident.
// O `param.name` é NameId. // `param.name` is a NameId.
} }
} }
if let Some(ret) = n.ret { if let Some(ret) = n.ret {

View File

@ -335,7 +335,7 @@ impl PrometeuOS {
} }
// Helper para syscalls // Helper for syscalls
fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> { fn syscall_log_write(&mut self, level_val: i64, tag: u16, msg: String) -> Result<(), VmFault> {
let level = match level_val { let level = match level_val {
0 => LogLevel::Trace, 0 => LogLevel::Trace,
@ -370,11 +370,11 @@ impl PrometeuOS {
} }
pub fn get_color(&self, value: i64) -> Color { pub fn get_color(&self, value: i64) -> Color {
// Agora usamos o valor diretamente como RGB565. // We now use the value directly as RGB565.
Color::from_raw(value as u16) Color::from_raw(value as u16)
} }
// Helper para syscalls // Helper for syscalls
pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a prometeu_abi::model::Button> { pub fn get_button<'a>(&self, id: u32, hw: &'a dyn HardwareBridge) -> Option<&'a prometeu_abi::model::Button> {
let pad = hw.pad(); let pad = hw.pad();
match id { match id {

View File

@ -24,7 +24,7 @@ impl tower_lsp::LanguageServer for Backend {
tower_lsp::lsp_types::TextDocumentSyncKind::FULL, tower_lsp::lsp_types::TextDocumentSyncKind::FULL,
), ),
), ),
// Declaramos capacidades desde já para evitar churn posterior. // Declare capabilities up front to avoid later churn.
definition_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), definition_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)),
document_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), document_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)),
workspace_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)), workspace_symbol_provider: Some(tower_lsp::lsp_types::OneOf::Left(true)),
@ -40,7 +40,7 @@ impl tower_lsp::LanguageServer for Backend {
tower_lsp::lsp_types::SemanticTokensServerCapabilities::SemanticTokensOptions( tower_lsp::lsp_types::SemanticTokensServerCapabilities::SemanticTokensOptions(
tower_lsp::lsp_types::SemanticTokensOptions { tower_lsp::lsp_types::SemanticTokensOptions {
legend: tower_lsp::lsp_types::SemanticTokensLegend { legend: tower_lsp::lsp_types::SemanticTokensLegend {
// preenchido no PR-12 // filled in PR-12
token_types: vec![], token_types: vec![],
token_modifiers: vec![], token_modifiers: vec![],
}, },

View File

@ -2,10 +2,10 @@ use tokio_util::sync::CancellationToken;
use crate::analysis_db::SharedDb; use crate::analysis_db::SharedDb;
/// Solicita rebuild do projeto (coarse). Cancela rebuild anterior se em progresso. /// Requests a project rebuild (coarse). Cancels the previous rebuild if in progress.
/// Implementação inicial: apenas cria task e retorna. /// Initial implementation: only spawns a task and returns.
pub async fn request_rebuild(db: SharedDb) { pub async fn request_rebuild(db: SharedDb) {
// 1) lock curto: cancelar token anterior e instalar token novo // 1) short lock: cancel previous token and install a new one
let new_token = CancellationToken::new(); let new_token = CancellationToken::new();
{ {
let mut guard = db.write().await; let mut guard = db.write().await;
@ -15,33 +15,33 @@ pub async fn request_rebuild(db: SharedDb) {
guard.active_rebuild = Some(new_token.clone()); guard.active_rebuild = Some(new_token.clone());
} }
// 2) spawn task: roda análise fora do lock // 2) spawn task: run analysis outside the lock
tokio::spawn(async move { tokio::spawn(async move {
// Ponto seguro: checar antes de começar // Safe point: check before starting
if new_token.is_cancelled() { return; } if new_token.is_cancelled() { return; }
// TODO(PR-03/04/05): // TODO(PR-03/04/05):
// - Clonar snapshot de FileDB // - Clone FileDB snapshot
// - Parsing // - Parsing
// - Binding/Resolver // - Binding/Resolver
// - Typecheck // - Typecheck
// - Coleta de diagnostics // - Collect diagnostics
// Ponto seguro: após parsing // Safe point: after parsing
if new_token.is_cancelled() { return; } if new_token.is_cancelled() { return; }
// Ponto seguro: após resolver // Safe point: after resolving
if new_token.is_cancelled() { return; } if new_token.is_cancelled() { return; }
// Ponto seguro: após typecheck // Safe point: after typecheck
if new_token.is_cancelled() { return; } if new_token.is_cancelled() { return; }
// 3) lock curto: se token não cancelado, swap estado + revision++ // 3) short lock: if token not cancelled, swap state + revision++
if !new_token.is_cancelled() { if !new_token.is_cancelled() {
let mut guard = db.write().await; let mut guard = db.write().await;
// TODO: checar se o token ainda é o ativo quando tivermos um identificador estável // TODO: check if the token is still the active one when we have a stable identifier
if !new_token.is_cancelled() { if !new_token.is_cancelled() {
// TODO: aplicar resultados reais de análise quando disponíveis // TODO: apply real analysis results when available
guard.revision = guard.revision.saturating_add(1); guard.revision = guard.revision.saturating_add(1);
// Nota: não limpamos `active_rebuild` aqui para evitar interferir num rebuild mais novo // Note: we don't clear `active_rebuild` here to avoid interfering with a newer rebuild
} }
} }
}); });