Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve documentation comments of some commonly used types #2922

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 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
47 changes: 44 additions & 3 deletions Sources/SwiftSyntax/generated/SyntaxBaseNodes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,28 @@ extension Syntax {
}
}

/// A type-erased expression node in the Swift syntax tree.
///
/// This type provides a common API for working with any kind of Swift expression. It can represent various expression types like:
/// - Function calls (`print("Hello")`)
/// - Literals (`42`, `true`, `"text"`)
/// - Member access (`object.property`)
/// - Operators (`a + b`)
/// - And many more
///
/// Example converting a specific expression type to ExprSyntax:
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// ```swift
/// let specificExpr = StringLiteralExprSyntax(content: "Hello")
/// let genericExpr = ExprSyntax(specificExpr)
/// ```
///
/// Example checking and converting back to a specific type:
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// ```swift
/// if let stringLiteral = expr.as(StringLiteralExprSyntax.self) {
/// // Work with the specific string literal expression
/// }
/// ```
///
/// ### Subtypes
///
/// - ``ArrayExprSyntax``
Expand Down Expand Up @@ -509,37 +531,56 @@ extension Syntax {
public struct ExprSyntax: ExprSyntaxProtocol, SyntaxHashable {
public let _syntaxNode: Syntax

/// Create a ``ExprSyntax`` node from a specialized syntax node.
/// Creates a type-erased expression from a specialized expression syntax node.
///
/// - Parameters:
/// - syntax: The specialized expression node to convert to a generic ExprSyntax.
public init(_ syntax: __shared some ExprSyntaxProtocol) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self = Syntax(syntax).cast(Self.self)
}

/// Create a ``ExprSyntax`` node from a specialized optional syntax node.
/// Creates an optional type-erased expression from an optional specialized expression syntax node.
///
/// - Parameters:
/// - syntax: The optional specialized expression node to convert to a generic ExprSyntax.
public init?(_ syntax: __shared (some ExprSyntaxProtocol)?) {
guard let syntax = syntax else {
return nil
}
self.init(syntax)
}

/// Creates a type-erased expression from an expression protocol type.
///
/// - Parameters:
/// - syntax: The expression protocol type to convert to a generic ExprSyntax.
public init(fromProtocol syntax: __shared ExprSyntaxProtocol) {
// We know this cast is going to succeed. Go through init(_: SyntaxData)
// to do a sanity check and verify the kind matches in debug builds and get
// maximum performance in release builds.
self = Syntax(syntax).cast(Self.self)
}

/// Create a ``ExprSyntax`` node from a specialized optional syntax node.
/// Creates an optional type-erased expression from an optional expression protocol type.
///
/// - Parameters:
/// - syntax: The optional expression protocol type to convert to a generic ExprSyntax.
public init?(fromProtocol syntax: __shared ExprSyntaxProtocol?) {
guard let syntax = syntax else {
return nil
}
self.init(fromProtocol: syntax)
}

/// Creates a type-erased expression from any syntax node that represents an expression.
///
/// This initializer succeeds only for syntax nodes that represent valid Swift expressions.
///
/// - Parameters:
/// - node: The syntax node to convert. Must be one of the supported expression kinds.
public init?(_ node: __shared some SyntaxProtocol) {
switch node.raw.kind {
case .arrayExpr, .arrowExpr, .asExpr, .assignmentExpr, .awaitExpr, .binaryOperatorExpr, .booleanLiteralExpr, .borrowExpr, ._canImportExpr, ._canImportVersionInfo, .closureExpr, .consumeExpr, .copyExpr, .declReferenceExpr, .dictionaryExpr, .discardAssignmentExpr, .doExpr, .editorPlaceholderExpr, .floatLiteralExpr, .forceUnwrapExpr, .functionCallExpr, .genericSpecializationExpr, .ifExpr, .inOutExpr, .infixOperatorExpr, .integerLiteralExpr, .isExpr, .keyPathExpr, .macroExpansionExpr, .memberAccessExpr, .missingExpr, .nilLiteralExpr, .optionalChainingExpr, .packElementExpr, .packExpansionExpr, .patternExpr, .postfixIfConfigExpr, .postfixOperatorExpr, .prefixOperatorExpr, .regexLiteralExpr, .sequenceExpr, .simpleStringLiteralExpr, .stringLiteralExpr, .subscriptCallExpr, .superExpr, .switchExpr, .ternaryExpr, .tryExpr, .tupleExpr, .typeExpr, .unresolvedAsExpr, .unresolvedIsExpr, .unresolvedTernaryExpr:
Expand Down
158 changes: 150 additions & 8 deletions Sources/SwiftSyntax/generated/SyntaxCollections.swift
Original file line number Diff line number Diff line change
Expand Up @@ -855,12 +855,42 @@ public struct KeyPathComponentListSyntax: SyntaxCollection, SyntaxHashable {
public static let syntaxKind = SyntaxKind.keyPathComponentList
}

/// A list of labeled expressions used in function calls, macro expansions, and other contexts where arguments can have labels.
///
/// This collection represents a list of expressions that may have labels, such as function call arguments or macro parameters.
///
/// Example of creating a list of labeled arguments:
/// ```swift
/// let arguments = LabeledExprListSyntax {
/// LabeledExprSyntax(
/// label: .identifier("localized"),
/// colon: .colonToken(),
/// expression: stringLiteral
/// )
/// LabeledExprSyntax(
/// label: .identifier("defaultValue"),
/// colon: .colonToken(),
/// expression: defaultValueLiteral
/// )
/// }
/// ```
///
/// Example of creating a function call with labeled arguments:
/// ```swift
/// let functionCall = FunctionCallExprSyntax(
/// calledExpression: ExprSyntax(name),
/// leftParen: .leftParenToken(),
/// arguments: arguments,
/// rightParen: .rightParenToken()
/// )
/// ```
///
/// ### Children
///
///
/// ``LabeledExprSyntax`` `*`
///
/// ### Contained in
///
///
/// - ``AttributeSyntax``.``AttributeSyntax/arguments``
/// - ``ExpressionSegmentSyntax``.``ExpressionSegmentSyntax/expressions``
/// - ``FunctionCallExprSyntax``.``FunctionCallExprSyntax/arguments``
Expand All @@ -874,6 +904,21 @@ public struct LabeledExprListSyntax: SyntaxCollection, SyntaxHashable {

public let _syntaxNode: Syntax

/// Creates a list of labeled expressions from a syntax node.
///
/// Example:
/// ```swift
/// let arguments = LabeledExprListSyntax {
/// LabeledExprSyntax(
/// label: .identifier("name"),
/// colon: .colonToken(),
/// expression: nameExpr
/// )
/// }
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// ```
///
/// - Parameters:
/// - node: The syntax node to create the list from. Must be of kind `.labeledExprList`.
public init?(_ node: some SyntaxProtocol) {
guard node.raw.kind == .labeledExprList else {
return nil
Expand Down Expand Up @@ -1397,21 +1442,56 @@ public struct SpecializeAttributeArgumentListSyntax: SyntaxCollection, SyntaxHas
public static let syntaxKind = SyntaxKind.specializeAttributeArgumentList
}

/// A collection of string literal segments representing both plain text and interpolated expressions.
///
/// This collection is used to represent the contents of string literals, including both static text segments and interpolated expressions.
/// For example, in the string literal `"Hello \(name)"`, the collection would contain a string segment for `"Hello "` followed by an expression segment for `\(name)`.
///
/// ```swift
/// let segments = StringLiteralSegmentListSyntax([
/// .stringSegment(.init(content: .stringSegment("Hello "))),
/// .expressionSegment(/* interpolation expression */)
/// ])
/// ```
///
/// This type is commonly used in macros for:
/// - Building string literals with both static text and interpolations
/// - Validating string literal contents at compile time
/// - Analyzing or transforming string interpolations
///
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// ### Children
///
///
/// (``StringSegmentSyntax`` | ``ExpressionSegmentSyntax``) `*`
///
/// ### Contained in
///
///
/// - ``StringLiteralExprSyntax``.``StringLiteralExprSyntax/segments``
public struct StringLiteralSegmentListSyntax: SyntaxCollection, SyntaxHashable {
/// Represents either a literal string segment or an interpolated expression segment within a string literal.
///
/// This enum is used to handle the two possible types of segments that can appear in a string literal:
/// - Plain text segments (like `"Hello "` in `"Hello \(name)"`)
/// - Expression segments (like `\(name)` in `"Hello \(name)"`)
///
/// Example:
/// ```swift
/// let segments = [
/// StringLiteralSegmentListSyntax.Element.stringSegment(.init(content: .stringSegment("Hello "))),
/// StringLiteralSegmentListSyntax.Element.expressionSegment(/* expression */)
/// ]
/// ```
public enum Element: SyntaxChildChoices, SyntaxHashable {
/// A literal segment inside a string segment.
///
/// A literal text segment inside a string literal.
///
/// This case represents static text content like `"Hello "` in `"Hello \(name)"`.
///
/// - SeeAlso: ``ExpressionSegmentSyntax``
case stringSegment(StringSegmentSyntax)
/// An interpolated expression inside a string literal.
///

/// An interpolated expression segment inside a string literal.
///
/// This case represents interpolated expressions like `\(name)` in `"Hello \(name)"`.
///
/// - SeeAlso: ``StringSegmentSyntax``
case expressionSegment(ExpressionSegmentSyntax)

Expand All @@ -1424,14 +1504,59 @@ public struct StringLiteralSegmentListSyntax: SyntaxCollection, SyntaxHashable {
}
}

/// Creates a new Element wrapping a string segment.
///
/// This initializer is used when adding literal text content to a string literal. The string segment should be created using `.stringSegment()` to ensure proper formatting.
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
///
/// Example from warning macro:
/// ```swift
/// let element = StringLiteralSegmentListSyntax.Element(
/// StringSegmentSyntax(content: .stringSegment("warning: invalid configuration"))
/// )
/// ```
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
///
/// - Parameters:
/// - node: The string segment to wrap in this element.
public init(_ node: StringSegmentSyntax) {
self = .stringSegment(node)
}

/// Creates a new Element wrapping an expression segment.
///
/// This initializer is used when adding interpolated expressions to a string literal.
///
/// Example from diagnostic message:
/// ```swift
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// let element = StringLiteralSegmentListSyntax.Element(
/// ExpressionSegmentSyntax(
/// expressions: ExprListSyntax([
/// ExprSyntax("errorValue")
/// ])
/// )
/// )
/// ```
///
/// - Parameters:
/// - node: The expression segment to wrap in this element.
public init(_ node: ExpressionSegmentSyntax) {
self = .expressionSegment(node)
}

/// Creates a new Element from an existing syntax node by attempting to cast it to either a string or expression segment.
///
/// Example from string literal parsing:
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
/// ```swift
/// guard
/// let stringLiteral = node.as(StringLiteralExprSyntax.self),
/// let firstSegment = stringLiteral.segments.first,
/// case .stringSegment(let segment) = firstSegment
/// else {
/// throw CustomError.message("Expected string literal")
/// }
/// ```
///
/// - Parameters:
/// - node: The syntax node to attempt to convert into an element. Must be either a StringSegmentSyntax or ExpressionSegmentSyntax.
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
public init?(_ node: __shared some SyntaxProtocol) {
if let node = node.as(StringSegmentSyntax.self) {
self = .stringSegment(node)
Expand Down Expand Up @@ -1493,6 +1618,23 @@ public struct StringLiteralSegmentListSyntax: SyntaxCollection, SyntaxHashable {

public let _syntaxNode: Syntax

/// Creates a list of string literal segments from an array of elements.
///
/// Used to create lists that represent both plain text and interpolated expressions in a string literal. Common in macros where you need to create or modify string literals.
///
/// Example:
/// ```swift
/// let stringLiteral = StringLiteralExprSyntax(
/// openingQuote: .stringQuoteToken(),
/// segments: StringLiteralSegmentListSyntax([
/// .stringSegment(.init(content: .stringSegment("Hello")))
/// ]),
/// closingQuote: .stringQuoteToken()
/// )
/// ```
///
/// - Parameters:
/// - node: The syntax node to create the list from. Must be of kind `.stringLiteralSegmentList`.
Jeehut marked this conversation as resolved.
Show resolved Hide resolved
public init?(_ node: some SyntaxProtocol) {
guard node.raw.kind == .stringLiteralSegmentList else {
return nil
Expand Down
51 changes: 47 additions & 4 deletions Sources/SwiftSyntax/generated/syntaxNodes/SyntaxNodesD.swift
Original file line number Diff line number Diff line change
Expand Up @@ -605,13 +605,35 @@ public struct DeclNameArgumentsSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt

// MARK: - DeclReferenceExprSyntax

/// An expression that refers to a declaration by name, such as a reference to a function, type, or variable.
///
/// This type represents references to declarations in Swift code, commonly used when building syntax for:
/// - Function and type references
/// - Variable and property references
/// - Special declarations like `self`, `Self`, and `init`
///
/// Example creating a simple reference to a type:
/// ```swift
/// let stringReference = DeclReferenceExprSyntax(baseName: "String")
/// ```
///
/// Example using a declaration reference in a function call:
/// ```swift
/// let functionCall = FunctionCallExprSyntax(
/// calledExpression: DeclReferenceExprSyntax(baseName: "print"),
/// leftParen: .leftParenToken(),
/// arguments: arguments,
/// rightParen: .rightParenToken()
/// )
/// ```
///
/// ### Children
///
///
/// - `baseName`: (`<identifier>` | `self` | `Self` | `init` | `deinit` | `subscript` | `<dollarIdentifier>` | `<binaryOperator>` | `<integerLiteral>`)
/// - `argumentNames`: ``DeclNameArgumentsSyntax``?
///
/// ### Contained in
///
///
/// - ``DynamicReplacementAttributeArgumentsSyntax``.``DynamicReplacementAttributeArgumentsSyntax/declName``
/// - ``ImplementsAttributeArgumentsSyntax``.``ImplementsAttributeArgumentsSyntax/declName``
/// - ``KeyPathPropertyComponentSyntax``.``KeyPathPropertyComponentSyntax/declName``
Expand All @@ -620,16 +642,37 @@ public struct DeclNameArgumentsSyntax: SyntaxProtocol, SyntaxHashable, _LeafSynt
public struct DeclReferenceExprSyntax: ExprSyntaxProtocol, SyntaxHashable, _LeafExprSyntaxNodeProtocol {
public let _syntaxNode: Syntax

/// Internal initializer used by swift-syntax to create declaration references from existing syntax nodes.
///
/// This initializer is not intended for direct use when creating declaration references programmatically.
/// Instead, use the main initializer that accepts individual components.
///
/// - Parameters:
/// - node: An existing syntax node to convert. Must be of kind `.declReferenceExpr`.
public init?(_ node: __shared some SyntaxProtocol) {
guard node.raw.kind == .declReferenceExpr else {
return nil
}
self._syntaxNode = node._syntaxNode
}

/// Creates a new declaration reference with the given base name and optional components.
///
/// Example creating a reference to a type:
/// ```swift
/// let reference = DeclReferenceExprSyntax(
/// baseName: .identifier("String")
/// )
/// ```
///
/// - Parameters:
/// - leadingTrivia: Trivia to be prepended to the leading trivia of the node’s first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
/// - trailingTrivia: Trivia to be appended to the trailing trivia of the node’s last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
/// - leadingTrivia: Trivia to be prepended to the leading trivia of the node's first token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
/// - unexpectedBeforeBaseName: Used internally by swift-syntax to handle malformed source code. When creating expressions programmatically, you should pass nil.
/// - baseName: The name of the declaration being referenced.
/// - unexpectedBetweenBaseNameAndArgumentNames: Used internally by swift-syntax to handle malformed source code. When creating expressions programmatically, you should pass nil.
/// - argumentNames: Optional argument labels when referring to specific function overloads.
/// - unexpectedAfterArgumentNames: Used internally by swift-syntax to handle malformed source code. When creating expressions programmatically, you should pass nil.
/// - trailingTrivia: Trivia to be appended to the trailing trivia of the node's last token. If the node is empty, there is no token to attach the trivia to and the parameter is ignored.
public init(
leadingTrivia: Trivia? = nil,
_ unexpectedBeforeBaseName: UnexpectedNodesSyntax? = nil,
Expand Down
Loading