From dc5b1a182ef5a341aa31f58e1188a5563a1386f9 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Wed, 21 Jun 2023 23:08:08 +0200 Subject: [PATCH] Use trait for labels instead of `TypeId` --- crates/ruff_formatter/src/builders.rs | 27 ++++++++--- .../ruff_formatter/src/format_element/tag.rs | 46 +++++++++++-------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/crates/ruff_formatter/src/builders.rs b/crates/ruff_formatter/src/builders.rs index 1f3ef8fff1846..441fb00a958d9 100644 --- a/crates/ruff_formatter/src/builders.rs +++ b/crates/ruff_formatter/src/builders.rs @@ -528,7 +528,22 @@ impl Format for LineSuffixBoundary { /// use ruff_formatter::prelude::*; /// use ruff_formatter::{format, write, LineWidth}; /// -/// enum SomeLabelId {} +/// #[derive(Debug, Copy, Clone)] +/// enum MyLabels { +/// Main +/// } +/// +/// impl tag::LabelDefinition for MyLabels { +/// fn value(&self) -> u64 { +/// *self as u64 +/// } +/// +/// fn name(&self) -> &'static str { +/// match self { +/// Self::Main => "Main" +/// } +/// } +/// } /// /// # fn main() -> FormatResult<()> { /// let formatted = format!( @@ -537,24 +552,24 @@ impl Format for LineSuffixBoundary { /// let mut recording = f.start_recording(); /// write!(recording, [ /// labelled( -/// LabelId::of::(), +/// LabelId::of(MyLabels::Main), /// &text("'I have a label'") /// ) /// ])?; /// /// let recorded = recording.stop(); /// -/// let is_labelled = recorded.first().map_or(false, |element| element.has_label(LabelId::of::())); +/// let is_labelled = recorded.first().map_or(false, |element| element.has_label(LabelId::of(MyLabels::Main))); /// /// if is_labelled { -/// write!(f, [text(" has label SomeLabelId")]) +/// write!(f, [text(" has label `Main`")]) /// } else { -/// write!(f, [text(" doesn't have label SomeLabelId")]) +/// write!(f, [text(" doesn't have label `Main`")]) /// } /// })] /// )?; /// -/// assert_eq!("'I have a label' has label SomeLabelId", formatted.print()?.as_code()); +/// assert_eq!("'I have a label' has label `Main`", formatted.print()?.as_code()); /// # Ok(()) /// # } /// ``` diff --git a/crates/ruff_formatter/src/format_element/tag.rs b/crates/ruff_formatter/src/format_element/tag.rs index 6c8d03c20be81..a443f909f0f8c 100644 --- a/crates/ruff_formatter/src/format_element/tag.rs +++ b/crates/ruff_formatter/src/format_element/tag.rs @@ -1,8 +1,5 @@ use crate::format_element::PrintMode; use crate::{GroupId, TextSize}; -#[cfg(debug_assertions)] -use std::any::type_name; -use std::any::TypeId; use std::cell::Cell; use std::num::NonZeroU8; @@ -235,37 +232,48 @@ impl Align { } } -#[derive(Eq, PartialEq, Copy, Clone)] +#[derive(Debug, Eq, Copy, Clone)] pub struct LabelId { - id: TypeId, + value: u64, #[cfg(debug_assertions)] - label: &'static str, + name: &'static str, } -#[cfg(debug_assertions)] -impl std::fmt::Debug for LabelId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(self.label) - } -} +impl PartialEq for LabelId { + fn eq(&self, other: &Self) -> bool { + let is_equal = self.value == other.value; + + #[cfg(debug_assertions)] + { + if is_equal { + assert_eq!(self.name, other.name, "Two `LabelId`s with different names have the same `value`. Are you mixing labels of two different `LabelDefinition` or are the values returned by the `LabelDefinition` not unique?"); + } + } -#[cfg(not(debug_assertions))] -impl std::fmt::Debug for LabelId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - std::write!(f, "#{:?}", self.id) + is_equal } } impl LabelId { - pub fn of() -> Self { + pub fn of(label: T) -> Self { Self { - id: TypeId::of::(), + value: label.value(), #[cfg(debug_assertions)] - label: type_name::(), + name: label.name(), } } } +/// Defines the valid labels of a language. You want to have at most one implementation per formatter +/// project. +pub trait LabelDefinition { + /// Returns the `u64` uniquely identifying this specific label. + fn value(&self) -> u64; + + /// Returns the name of the label that is shown in debug builds. + fn name(&self) -> &'static str; +} + #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum VerbatimKind { Bogus,