From 335b7f22c52ab3cbcc498155c5f9adb25a30b251 Mon Sep 17 00:00:00 2001 From: DonIsaac <22823424+DonIsaac@users.noreply.github.com> Date: Tue, 15 Oct 2024 22:50:45 +0000 Subject: [PATCH] docs(syntax): enable lint warnings on missing docs, and add a lot of documentation (#6611) Part of https://github.com/oxc-project/backlog/issues/130 I didn't add doc comments to everything; I'm missing context for module-related data types and I have other things to do :P --- crates/oxc_syntax/src/class.rs | 2 + crates/oxc_syntax/src/identifier.rs | 1 + crates/oxc_syntax/src/keyword.rs | 13 +++ crates/oxc_syntax/src/lib.rs | 2 +- crates/oxc_syntax/src/module_graph_visitor.rs | 1 + crates/oxc_syntax/src/module_record.rs | 16 +++ crates/oxc_syntax/src/node.rs | 14 ++- crates/oxc_syntax/src/number.rs | 1 + crates/oxc_syntax/src/operator.rs | 105 ++++++++++++++++++ crates/oxc_syntax/src/precedence.rs | 1 + crates/oxc_syntax/src/reference.rs | 1 + crates/oxc_syntax/src/scope.rs | 1 + crates/oxc_syntax/src/symbol.rs | 1 + crates/oxc_syntax/src/xml_entities.rs | 1 + 14 files changed, 156 insertions(+), 4 deletions(-) diff --git a/crates/oxc_syntax/src/class.rs b/crates/oxc_syntax/src/class.rs index d9ed01b17e25b..d0c82429b0811 100644 --- a/crates/oxc_syntax/src/class.rs +++ b/crates/oxc_syntax/src/class.rs @@ -1,3 +1,5 @@ +//! Class and class element syntax items +#![allow(missing_docs)] // fixme use bitflags::bitflags; use oxc_index::define_index_type; diff --git a/crates/oxc_syntax/src/identifier.rs b/crates/oxc_syntax/src/identifier.rs index ef5343f148beb..dfa757eb8deba 100644 --- a/crates/oxc_syntax/src/identifier.rs +++ b/crates/oxc_syntax/src/identifier.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use assert_unchecked::assert_unchecked; use unicode_id_start::{is_id_continue_unicode, is_id_start_unicode}; diff --git a/crates/oxc_syntax/src/keyword.rs b/crates/oxc_syntax/src/keyword.rs index bc556413f8810..bed8bb45c4f29 100644 --- a/crates/oxc_syntax/src/keyword.rs +++ b/crates/oxc_syntax/src/keyword.rs @@ -1,10 +1,23 @@ +//! Keywords and reserved words in ECMAScript. +//! +//! ## References +//! - [12.7.2 Keywords and Reserved Words](https://tc39.es/ecma262/#sec-keywords-and-reserved-words) use phf::{phf_set, Set}; +/// Checks if the given string is a [reserved keyword] or a [global object] +/// (e.g. `NaN`). +/// +/// [reserved keyword]: is_reserved_keyword +/// [global object]: is_global_object #[inline] pub fn is_reserved_keyword_or_global_object(s: &str) -> bool { is_reserved_keyword(s) || is_global_object(s) } +/// Checks if the given string is a reserved keyword. +/// +/// Reserved keywords are either keywords currently used in the ECMAScript spec, +/// or words that are reserved for future use. #[inline] pub fn is_reserved_keyword(s: &str) -> bool { RESERVED_KEYWORDS.contains(s) diff --git a/crates/oxc_syntax/src/lib.rs b/crates/oxc_syntax/src/lib.rs index c64073bbb4208..8e5388f5190f3 100644 --- a/crates/oxc_syntax/src/lib.rs +++ b/crates/oxc_syntax/src/lib.rs @@ -1,5 +1,5 @@ //! Common code for JavaScript Syntax - +#![warn(missing_docs)] pub mod class; pub mod identifier; pub mod keyword; diff --git a/crates/oxc_syntax/src/module_graph_visitor.rs b/crates/oxc_syntax/src/module_graph_visitor.rs index 03780bdc80851..b4c7f6eff04c9 100644 --- a/crates/oxc_syntax/src/module_graph_visitor.rs +++ b/crates/oxc_syntax/src/module_graph_visitor.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use std::{marker::PhantomData, path::PathBuf, sync::Arc}; use oxc_span::CompactStr; diff --git a/crates/oxc_syntax/src/module_record.rs b/crates/oxc_syntax/src/module_record.rs index 45bb5ceba6cec..3a192b1401c34 100644 --- a/crates/oxc_syntax/src/module_record.rs +++ b/crates/oxc_syntax/src/module_record.rs @@ -1,4 +1,5 @@ //! [ECMAScript Module Record](https://tc39.es/ecma262/#sec-abstract-module-records) +#![allow(missing_docs)] // fixme use std::{fmt, hash::BuildHasherDefault, path::PathBuf, sync::Arc}; @@ -302,14 +303,17 @@ pub enum ExportExportName { } impl ExportExportName { + /// Returns `true` if this is [`ExportExportName::Default`]. pub fn is_default(&self) -> bool { matches!(self, Self::Default(_)) } + /// Returns `true` if this is [`ExportExportName::Null`]. pub fn is_null(&self) -> bool { matches!(self, Self::Null) } + /// Attempt to get the [`Span`] of this export name. pub fn span(&self) -> Option { match self { Self::Name(name) => Some(name.span()), @@ -330,14 +334,17 @@ pub enum ExportLocalName { } impl ExportLocalName { + /// `true` if this is a [`ExportLocalName::Default`]. pub fn is_default(&self) -> bool { matches!(self, Self::Default(_)) } + /// `true` if this is a [`ExportLocalName::Null`]. pub fn is_null(&self) -> bool { matches!(self, Self::Null) } + /// Get the bound name of this export. [`None`] for [`ExportLocalName::Null`]. pub const fn name(&self) -> Option<&CompactStr> { match self { Self::Name(name) | Self::Default(name) => Some(name.name()), @@ -367,10 +374,19 @@ impl RequestedModule { self.span } + /// `true` if a `type` modifier was used in the import statement. + /// + /// ## Examples + /// ```ts + /// import type { foo } from "foo"; // true, `type` is on module request + /// import { type bar } from "bar"; // false, `type` is on specifier + /// import { baz } from "baz"; // false, no `type` modifier + /// ``` pub fn is_type(&self) -> bool { self.is_type } + /// `true` if the module is requested by an import statement. pub fn is_import(&self) -> bool { self.is_import } diff --git a/crates/oxc_syntax/src/node.rs b/crates/oxc_syntax/src/node.rs index 937a1a9715d12..be2dbdaa44703 100644 --- a/crates/oxc_syntax/src/node.rs +++ b/crates/oxc_syntax/src/node.rs @@ -1,3 +1,4 @@ +//! AST Node ID and flags. use bitflags::bitflags; use nonmax::NonMaxU32; use oxc_index::Idx; @@ -9,6 +10,9 @@ use serde::{Serialize, Serializer}; pub struct NodeId(NonMaxU32); impl NodeId { + /// Mock node id. + /// + /// This is used for synthetically-created AST nodes, among other things. pub const DUMMY: Self = NodeId::new(0); /// Create `NodeId` from `u32`. @@ -69,11 +73,15 @@ export type NodeFlags = { "#; bitflags! { + /// Contains additional information about an AST node. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct NodeFlags: u8 { - const JSDoc = 1 << 0; // If the Node has a JSDoc comment attached - const Class = 1 << 1; // If Node is inside a class - const HasYield = 1 << 2; // If function has yield statement + /// Set if the Node has a JSDoc comment attached + const JSDoc = 1 << 0; + /// Set on Nodes inside classes + const Class = 1 << 1; + /// Set functions containing yield statements + const HasYield = 1 << 2; } } diff --git a/crates/oxc_syntax/src/number.rs b/crates/oxc_syntax/src/number.rs index 159deb58e6554..3bbe84089d192 100644 --- a/crates/oxc_syntax/src/number.rs +++ b/crates/oxc_syntax/src/number.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use oxc_allocator::CloneIn; use oxc_ast_macros::ast; use oxc_span::{cmp::ContentEq, hash::ContentHash}; diff --git a/crates/oxc_syntax/src/operator.rs b/crates/oxc_syntax/src/operator.rs index 56f28112c7067..c52d75a929446 100644 --- a/crates/oxc_syntax/src/operator.rs +++ b/crates/oxc_syntax/src/operator.rs @@ -1,3 +1,6 @@ +//! ECMAScript operators. +//! +//! Not all operators are punctuation - some, such as `delete`, are keywords. // Silence erroneous warnings from Rust Analyser for `#[derive(Tsify)]` #![allow(non_snake_case)] @@ -9,50 +12,72 @@ use {serde::Serialize, tsify::Tsify}; use crate::precedence::{GetPrecedence, Precedence}; +/// Operators that may be used in assignment epxressions. +/// +/// ## References +/// - [13.15 Assignment Operators](https://tc39.es/ecma262/#sec-assignment-operators) #[ast] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] pub enum AssignmentOperator { + /// `=` #[serde(rename = "=")] Assign = 0, + /// `+=` #[serde(rename = "+=")] Addition = 1, + /// `-=` #[serde(rename = "-=")] Subtraction = 2, + /// `*=` #[serde(rename = "*=")] Multiplication = 3, + /// `/=` #[serde(rename = "/=")] Division = 4, + /// `%=` #[serde(rename = "%=")] Remainder = 5, + /// `<<=` #[serde(rename = "<<=")] ShiftLeft = 6, + /// `>>=` #[serde(rename = ">>=")] ShiftRight = 7, + /// `>>>=` #[serde(rename = ">>>=")] ShiftRightZeroFill = 8, + /// `|=` #[serde(rename = "|=")] BitwiseOR = 9, + /// `^=` #[serde(rename = "^=")] BitwiseXOR = 10, + /// `&=` #[serde(rename = "&=")] BitwiseAnd = 11, + /// `&&=` #[serde(rename = "&&=")] LogicalAnd = 12, + /// `||=` #[serde(rename = "||=")] LogicalOr = 13, + /// `??=` #[serde(rename = "??=")] LogicalNullish = 14, + /// `**=` #[serde(rename = "**=")] Exponential = 15, } impl AssignmentOperator { + /// Returns `true` for '||=`, `&&=`, and `??=`. pub fn is_logical(self) -> bool { matches!(self, Self::LogicalAnd | Self::LogicalOr | Self::LogicalNullish) } + /// Returns `true` for `+=`, `-=`, `*=`, `/=`, `%=`, and `**=`. #[rustfmt::skip] pub fn is_arithmetic(self) -> bool { matches!(self, Self::Addition | Self::Subtraction | Self::Multiplication @@ -60,6 +85,7 @@ impl AssignmentOperator { ) } + /// Returns `true` for `|=`, `^=`, `&=`, `<<=`, `>>=`, and `>>>=`. #[rustfmt::skip] pub fn is_bitwise(self) -> bool { matches!(self, Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd @@ -67,6 +93,9 @@ impl AssignmentOperator { ) } + /// Get the string representation of this operator. + /// + /// This is the same as how the operator appears in source code. pub fn as_str(&self) -> &'static str { match self { Self::Assign => "=", @@ -89,103 +118,143 @@ impl AssignmentOperator { } } +/// Operators used in binary expressions. Does not include logical binary +/// operators, which are in [`LogicalOperator`]. +/// +/// ## References +/// - [12.10 Binary Logical Operators](https://tc39.es/ecma262/#sec-binary-logical-operators) #[ast] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] pub enum BinaryOperator { + /// `==` #[serde(rename = "==")] Equality = 0, + /// `!=` #[serde(rename = "!=")] Inequality = 1, + /// `===` #[serde(rename = "===")] StrictEquality = 2, + /// `!==` #[serde(rename = "!==")] StrictInequality = 3, + /// `<` #[serde(rename = "<")] LessThan = 4, + /// `<=` #[serde(rename = "<=")] LessEqualThan = 5, + /// `>` #[serde(rename = ">")] GreaterThan = 6, + /// `>=` #[serde(rename = ">=")] GreaterEqualThan = 7, + /// `<<` #[serde(rename = "<<")] ShiftLeft = 8, + /// `>>` #[serde(rename = ">>")] ShiftRight = 9, + /// `>>>` #[serde(rename = ">>>")] ShiftRightZeroFill = 10, + /// `+` #[serde(rename = "+")] Addition = 11, + /// `-` #[serde(rename = "-")] Subtraction = 12, + /// `*` #[serde(rename = "*")] Multiplication = 13, + /// `/` #[serde(rename = "/")] Division = 14, + /// `%` #[serde(rename = "%")] Remainder = 15, + /// `|` #[serde(rename = "|")] BitwiseOR = 16, + /// `^` #[serde(rename = "^")] BitwiseXOR = 17, + /// `&` #[serde(rename = "&")] BitwiseAnd = 18, + /// `in` #[serde(rename = "in")] In = 19, + /// `instanceof` #[serde(rename = "instanceof")] Instanceof = 20, + /// `**` #[serde(rename = "**")] Exponential = 21, } impl BinaryOperator { + /// Returns `true` for inequality or inequality operarors #[rustfmt::skip] pub fn is_equality(self) -> bool { matches!(self, Self::Equality | Self::Inequality | Self::StrictEquality | Self::StrictInequality) } + /// Returns `true` for logical comparison operators #[rustfmt::skip] pub fn is_compare(self) -> bool { matches!(self, Self::LessThan | Self::LessEqualThan | Self::GreaterThan | Self::GreaterEqualThan) } + /// Returns `true` for arithmetic operators #[rustfmt::skip] pub fn is_arithmetic(self) -> bool { matches!(self, Self::Addition | Self::Subtraction | Self::Multiplication | Self::Division | Self::Remainder | Self::Exponential) } + /// Returns `true` for multiplication (`*`), division (`/`), and remainder + /// (`%`) operators pub fn is_multiplicative(self) -> bool { matches!(self, Self::Multiplication | Self::Division | Self::Remainder) } + /// Returns `true` for object relation operators pub fn is_relational(self) -> bool { matches!(self, Self::In | Self::Instanceof) } + /// Returns `true` if this is an [`In`](BinaryOperator::In) operator. pub fn is_in(self) -> bool { matches!(self, Self::In) } + /// Returns `true` for any bitwise operator #[rustfmt::skip] pub fn is_bitwise(self) -> bool { self.is_bitshift() || matches!(self, Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd) } + /// Returns `true` for any bitshift operator pub fn is_bitshift(self) -> bool { matches!(self, Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill) } + /// Returns `true` for any numeric or string binary operator pub fn is_numeric_or_string_binary_operator(self) -> bool { self.is_arithmetic() || self.is_bitwise() } + /// Returns `true` if this operator is a keyword instead of punctuation. pub fn is_keyword(self) -> bool { matches!(self, Self::In | Self::Instanceof) } + /// Try to get the operator that performs the inverse comparison operation. + /// [`None`] if this is not a comparison operator. pub fn compare_inverse_operator(self) -> Option { match self { Self::LessThan => Some(Self::GreaterThan), @@ -196,6 +265,8 @@ impl BinaryOperator { } } + /// Try to get the operator that performs the inverse equality operation. + /// [`None`] if this is not an equality operator. pub fn equality_inverse_operator(self) -> Option { match self { Self::Equality => Some(Self::Inequality), @@ -206,6 +277,7 @@ impl BinaryOperator { } } + /// The string representation of this operator as it appears in source code. pub fn as_str(&self) -> &'static str { match self { Self::Equality => "==", @@ -233,6 +305,9 @@ impl BinaryOperator { } } + /// Get the operator that has a lower precedence than this operator by a + /// single level. Use [`BinaryOperator::precedence`] to get the operator + /// with a higher precedence. pub fn lower_precedence(&self) -> Precedence { match self { Self::BitwiseOR => Precedence::LogicalAnd, @@ -278,20 +353,25 @@ impl GetPrecedence for BinaryOperator { } } +/// Logical binary operators #[ast] #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] pub enum LogicalOperator { + /// `||` #[serde(rename = "||")] Or = 0, + /// `&&` #[serde(rename = "&&")] And = 1, + /// `??` #[serde(rename = "??")] Coalesce = 2, } impl LogicalOperator { + /// Get the string representation of this operator as it appears in source code. pub fn as_str(&self) -> &'static str { match self { Self::Or => "||", @@ -300,6 +380,9 @@ impl LogicalOperator { } } + /// Get the operator that has a lower precedence than this operator by a + /// single level. Use [`BinaryOperator::precedence`] to get the operator + /// with a higher precedence. pub fn lower_precedence(&self) -> Precedence { match self { Self::Or => Precedence::NullishCoalescing, @@ -319,28 +402,42 @@ impl GetPrecedence for LogicalOperator { } } +/// Operators used in unary operators. +/// +/// Does not include self-modifying operators, which are in [`UpdateOperator`]. +/// +/// ## References +/// - [12.5 Unary Operators](https://tc39.es/ecma262/#sec-unary-operators) #[ast] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] pub enum UnaryOperator { + /// `-` #[serde(rename = "-")] UnaryNegation = 0, + /// `+` #[serde(rename = "+")] UnaryPlus = 1, + /// `!` #[serde(rename = "!")] LogicalNot = 2, + /// `~` #[serde(rename = "~")] BitwiseNot = 3, + /// `typeof` #[serde(rename = "typeof")] Typeof = 4, + /// `void` #[serde(rename = "void")] Void = 5, + /// `delete` #[serde(rename = "delete")] Delete = 6, } impl UnaryOperator { + /// Returns `true` if this operator is a unary arithmetic operator. pub fn is_arithmetic(self) -> bool { matches!(self, Self::UnaryNegation | Self::UnaryPlus) } @@ -352,18 +449,22 @@ impl UnaryOperator { matches!(self, Self::LogicalNot) } + /// Returns `true` if this operator is a bitwise operator. pub fn is_bitwise(self) -> bool { matches!(self, Self::BitwiseNot) } + /// Returns `true` if this is the [`void`](UnaryOperator::Void) operator. pub fn is_void(self) -> bool { matches!(self, Self::Void) } + /// Returns `true` if this operator is a keyword instead of punctuation. pub fn is_keyword(self) -> bool { matches!(self, Self::Typeof | Self::Void | Self::Delete) } + /// Get the string representation of this operator as it appears in source code. pub fn as_str(&self) -> &'static str { match self { Self::UnaryNegation => "-", @@ -377,18 +478,22 @@ impl UnaryOperator { } } +/// Unary update operators. #[ast] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[generate_derive(CloneIn, ContentEq, ContentHash)] #[cfg_attr(feature = "serialize", derive(Serialize, Tsify))] pub enum UpdateOperator { + /// `++` #[serde(rename = "++")] Increment = 0, + /// `--` #[serde(rename = "--")] Decrement = 1, } impl UpdateOperator { + /// Get the string representation of this operator as it appears in source code. pub fn as_str(&self) -> &'static str { match self { Self::Increment => "++", diff --git a/crates/oxc_syntax/src/precedence.rs b/crates/oxc_syntax/src/precedence.rs index 0077aa46f431b..8bd36182329e4 100644 --- a/crates/oxc_syntax/src/precedence.rs +++ b/crates/oxc_syntax/src/precedence.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme pub trait GetPrecedence { fn precedence(&self) -> Precedence; } diff --git a/crates/oxc_syntax/src/reference.rs b/crates/oxc_syntax/src/reference.rs index ea7f19fc96230..67d4df85cbbda 100644 --- a/crates/oxc_syntax/src/reference.rs +++ b/crates/oxc_syntax/src/reference.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use bitflags::bitflags; use nonmax::NonMaxU32; use oxc_allocator::CloneIn; diff --git a/crates/oxc_syntax/src/scope.rs b/crates/oxc_syntax/src/scope.rs index 258053c581699..f293637df0204 100644 --- a/crates/oxc_syntax/src/scope.rs +++ b/crates/oxc_syntax/src/scope.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use bitflags::bitflags; use nonmax::NonMaxU32; use oxc_index::Idx; diff --git a/crates/oxc_syntax/src/symbol.rs b/crates/oxc_syntax/src/symbol.rs index 0fa05c88a0631..be7a1ac887533 100644 --- a/crates/oxc_syntax/src/symbol.rs +++ b/crates/oxc_syntax/src/symbol.rs @@ -1,3 +1,4 @@ +#![allow(missing_docs)] // fixme use bitflags::bitflags; use nonmax::NonMaxU32; use oxc_index::Idx; diff --git a/crates/oxc_syntax/src/xml_entities.rs b/crates/oxc_syntax/src/xml_entities.rs index 1ccc250910148..7580c0b6ca80c 100644 --- a/crates/oxc_syntax/src/xml_entities.rs +++ b/crates/oxc_syntax/src/xml_entities.rs @@ -1,3 +1,4 @@ +//! XML Entities use phf::{phf_map, Map}; /// XML Entities