diff --git a/AGENTS.md b/AGENTS.md index 23f8cd7d..303cf107 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -259,6 +259,16 @@ cargo run -p plotnik-cli -- langs - Comments for seniors, not juniors - Rust 2024 `let` chains: `if let Some(x) = a && let Some(y) = b { ... }` +## Lifetime Conventions + +| Lifetime | Meaning | +| -------- | ------------------------------------------------ | +| `'q` | Query source string (`.ptk` file content) | +| `'d` | Diagnostics reference | +| `'s` | Source code string (tree-sitter input) | +| `'t` | Parsed tree-sitter tree | +| `'a` | Any other (generic borrows, bytecode views) | + # Testing Rules Code: `foo.rs` → tests: `foo_tests.rs` (include via `#[cfg(test)] mod foo_tests;`) diff --git a/crates/plotnik-lib/src/diagnostics/mod.rs b/crates/plotnik-lib/src/diagnostics/mod.rs index bc50f797..efe44a69 100644 --- a/crates/plotnik-lib/src/diagnostics/mod.rs +++ b/crates/plotnik-lib/src/diagnostics/mod.rs @@ -33,8 +33,8 @@ pub struct Diagnostics { } #[must_use = "diagnostic not emitted, call .emit()"] -pub struct DiagnosticBuilder<'a> { - diagnostics: &'a mut Diagnostics, +pub struct DiagnosticBuilder<'d> { + diagnostics: &'d mut Diagnostics, message: DiagnosticMessage, } @@ -169,12 +169,12 @@ impl Diagnostics { } /// Create a printer with a source map (multi-file support). - pub fn printer<'a>(&self, sources: &'a SourceMap) -> DiagnosticsPrinter<'a> { + pub fn printer<'q>(&self, sources: &'q SourceMap) -> DiagnosticsPrinter<'q> { DiagnosticsPrinter::new(self.messages.clone(), sources) } /// Filtered printer with source map (cascading errors suppressed). - pub fn filtered_printer<'a>(&self, sources: &'a SourceMap) -> DiagnosticsPrinter<'a> { + pub fn filtered_printer<'q>(&self, sources: &'q SourceMap) -> DiagnosticsPrinter<'q> { DiagnosticsPrinter::new(self.filtered(), sources) } @@ -203,7 +203,7 @@ impl Diagnostics { } } -impl<'a> DiagnosticBuilder<'a> { +impl<'d> DiagnosticBuilder<'d> { /// Provide custom detail for this diagnostic, rendered using the kind's template. pub fn message(mut self, msg: impl Into) -> Self { let detail = msg.into(); diff --git a/crates/plotnik-lib/src/diagnostics/printer.rs b/crates/plotnik-lib/src/diagnostics/printer.rs index 37e46f09..f43e1f0d 100644 --- a/crates/plotnik-lib/src/diagnostics/printer.rs +++ b/crates/plotnik-lib/src/diagnostics/printer.rs @@ -8,14 +8,14 @@ use rowan::TextRange; use super::SourceMap; use super::message::{DiagnosticMessage, Severity}; -pub struct DiagnosticsPrinter<'a> { +pub struct DiagnosticsPrinter<'q> { diagnostics: Vec, - sources: &'a SourceMap, + sources: &'q SourceMap, colored: bool, } -impl<'a> DiagnosticsPrinter<'a> { - pub(crate) fn new(diagnostics: Vec, sources: &'a SourceMap) -> Self { +impl<'q> DiagnosticsPrinter<'q> { + pub(crate) fn new(diagnostics: Vec, sources: &'q SourceMap) -> Self { Self { diagnostics, sources, @@ -112,7 +112,7 @@ impl<'a> DiagnosticsPrinter<'a> { Ok(()) } - fn source_path(&self, source: crate::query::SourceId) -> Option<&'a str> { + fn source_path(&self, source: crate::query::SourceId) -> Option<&'q str> { self.sources.path(source) } } diff --git a/crates/plotnik-lib/src/parser/ast.rs b/crates/plotnik-lib/src/parser/ast.rs index b3680db7..b952ab26 100644 --- a/crates/plotnik-lib/src/parser/ast.rs +++ b/crates/plotnik-lib/src/parser/ast.rs @@ -6,19 +6,19 @@ //! ## String Lifetime Limitation //! //! `SyntaxToken::text()` returns `&str` tied to the token's lifetime, not to the -//! source `&'src str`. This is a rowan design: tokens store interned strings, not +//! source `&'q str`. This is a rowan design: tokens store interned strings, not //! spans into the original source. //! //! When building data structures that need source-lifetime strings (e.g., -//! `SymbolTable<'src>`), use [`token_src`] instead of `token.text()`. +//! `SymbolTable<'q>`), use [`token_src`] instead of `token.text()`. use super::cst::{SyntaxKind, SyntaxNode, SyntaxToken}; use rowan::TextRange; /// Extracts token text with source lifetime. /// -/// Use this instead of `token.text()` when you need `&'src str`. -pub fn token_src<'src>(token: &SyntaxToken, source: &'src str) -> &'src str { +/// Use this instead of `token.text()` when you need `&'q str`. +pub fn token_src<'q>(token: &SyntaxToken, source: &'q str) -> &'q str { let range = token.text_range(); &source[range.start().into()..range.end().into()] } diff --git a/crates/plotnik-lib/src/parser/core.rs b/crates/plotnik-lib/src/parser/core.rs index 8897ade3..36b8d737 100644 --- a/crates/plotnik-lib/src/parser/core.rs +++ b/crates/plotnik-lib/src/parser/core.rs @@ -22,14 +22,14 @@ pub(super) struct OpenDelimiter { } /// Trivia tokens are buffered and flushed when starting a new node. -pub struct Parser<'src, 'diag> { - pub(super) source: &'src str, +pub struct Parser<'q, 'd> { + pub(super) source: &'q str, pub(super) source_id: SourceId, pub(super) tokens: Vec, pub(super) pos: usize, pub(super) trivia_buffer: Vec, pub(super) builder: GreenNodeBuilder<'static>, - pub(super) diagnostics: &'diag mut Diagnostics, + pub(super) diagnostics: &'d mut Diagnostics, pub(super) depth: u32, pub(super) last_diagnostic_pos: Option, pub(super) delimiter_stack: Vec, @@ -40,12 +40,12 @@ pub struct Parser<'src, 'diag> { fatal_error: Option, } -impl<'src, 'diag> Parser<'src, 'diag> { +impl<'q, 'd> Parser<'q, 'd> { pub fn new( - source: &'src str, + source: &'q str, source_id: SourceId, tokens: Vec, - diagnostics: &'diag mut Diagnostics, + diagnostics: &'d mut Diagnostics, fuel: u32, max_depth: u32, ) -> Self { diff --git a/crates/plotnik-lib/src/parser/lexer.rs b/crates/plotnik-lib/src/parser/lexer.rs index ff75ed0b..0e31fc42 100644 --- a/crates/plotnik-lib/src/parser/lexer.rs +++ b/crates/plotnik-lib/src/parser/lexer.rs @@ -109,6 +109,6 @@ fn split_string_literal(source: &str, span: Range, tokens: &mut Vec(source: &'src str, token: &Token) -> &'src str { +pub fn token_text<'q>(source: &'q str, token: &Token) -> &'q str { &source[std::ops::Range::::from(token.span)] } diff --git a/crates/plotnik-lib/src/query/query.rs b/crates/plotnik-lib/src/query/query.rs index c1bac431..27c0e128 100644 --- a/crates/plotnik-lib/src/query/query.rs +++ b/crates/plotnik-lib/src/query/query.rs @@ -154,10 +154,10 @@ pub type Query = QueryAnalyzed; /// Bundles references to the three main analysis artifacts that downstream /// modules (compile, emit) commonly need together. #[derive(Clone, Copy)] -pub struct QueryContext<'a> { - pub interner: &'a Interner, - pub type_ctx: &'a TypeContext, - pub symbol_table: &'a SymbolTable, +pub struct QueryContext<'q> { + pub interner: &'q Interner, + pub type_ctx: &'q TypeContext, + pub symbol_table: &'q SymbolTable, } pub struct QueryAnalyzed { diff --git a/crates/plotnik-lib/src/query/source_map.rs b/crates/plotnik-lib/src/query/source_map.rs index 6602d78c..bda95f7b 100644 --- a/crates/plotnik-lib/src/query/source_map.rs +++ b/crates/plotnik-lib/src/query/source_map.rs @@ -31,15 +31,15 @@ impl SourceKind { /// A borrowed view of a source: id, kind, and content. #[derive(Clone, Debug)] -pub struct Source<'a> { +pub struct Source<'q> { pub id: SourceId, - pub kind: &'a SourceKind, - pub content: &'a str, + pub kind: &'q SourceKind, + pub content: &'q str, } -impl<'a> Source<'a> { +impl<'q> Source<'q> { /// Returns the content string. - pub fn as_str(&self) -> &'a str { + pub fn as_str(&self) -> &'q str { self.content } }