Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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;`)
Expand Down
10 changes: 5 additions & 5 deletions crates/plotnik-lib/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down Expand Up @@ -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)
}

Expand Down Expand Up @@ -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<String>) -> Self {
let detail = msg.into();
Expand Down
10 changes: 5 additions & 5 deletions crates/plotnik-lib/src/diagnostics/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<DiagnosticMessage>,
sources: &'a SourceMap,
sources: &'q SourceMap,
colored: bool,
}

impl<'a> DiagnosticsPrinter<'a> {
pub(crate) fn new(diagnostics: Vec<DiagnosticMessage>, sources: &'a SourceMap) -> Self {
impl<'q> DiagnosticsPrinter<'q> {
pub(crate) fn new(diagnostics: Vec<DiagnosticMessage>, sources: &'q SourceMap) -> Self {
Self {
diagnostics,
sources,
Expand Down Expand Up @@ -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)
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/plotnik-lib/src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()]
}
Expand Down
12 changes: 6 additions & 6 deletions crates/plotnik-lib/src/parser/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Token>,
pub(super) pos: usize,
pub(super) trivia_buffer: Vec<Token>,
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<TextSize>,
pub(super) delimiter_stack: Vec<OpenDelimiter>,
Expand All @@ -40,12 +40,12 @@ pub struct Parser<'src, 'diag> {
fatal_error: Option<Error>,
}

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<Token>,
diagnostics: &'diag mut Diagnostics,
diagnostics: &'d mut Diagnostics,
fuel: u32,
max_depth: u32,
) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion crates/plotnik-lib/src/parser/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,6 @@ fn split_string_literal(source: &str, span: Range<usize>, tokens: &mut Vec<Token

/// Retrieves the text slice for a token. O(1) slice into source.
#[inline]
pub fn token_text<'src>(source: &'src str, token: &Token) -> &'src str {
pub fn token_text<'q>(source: &'q str, token: &Token) -> &'q str {
&source[std::ops::Range::<usize>::from(token.span)]
}
8 changes: 4 additions & 4 deletions crates/plotnik-lib/src/query/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
10 changes: 5 additions & 5 deletions crates/plotnik-lib/src/query/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down