//===--- DeclSyntax.h - Declaration Syntax Interface ------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file defines the interface for declaration-specific syntax nodes, // such as for structures, enumerations, type aliases, and constants. // //===----------------------------------------------------------------------===// #ifndef SWIFT_SYNTAX_DECLSYNTAX_H #define SWIFT_SYNTAX_DECLSYNTAX_H #include "swift/Syntax/GenericSyntax.h" #include "swift/Syntax/References.h" #include "swift/Syntax/RawSyntax.h" #include "swift/Syntax/Syntax.h" #include "swift/Syntax/SyntaxCollection.h" #include "swift/Syntax/SyntaxData.h" #include "swift/Syntax/TokenSyntax.h" #include "swift/Syntax/TypeSyntax.h" #include "swift/Syntax/UnknownSyntax.h" #include "llvm/ADT/BitVector.h" namespace swift { namespace syntax { class ExprSyntax; class ExprSyntaxData; #pragma mark declaration Data class DeclSyntaxData : public SyntaxData { protected: DeclSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); public: static bool classof(const SyntaxData *S) { return S->isDecl(); } }; #pragma mark declaration API class DeclSyntax : public Syntax { friend class Syntax; using DataType = DeclSyntaxData; protected: DeclSyntax(const RC Root, const DeclSyntaxData *Data); public: static bool classof(const SyntaxData *S) { return S->isDecl(); } }; #pragma mark - unknown-declaration Data class UnknownDeclSyntaxData : public UnknownSyntaxData { UnknownDeclSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); public: static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static bool classof(const SyntaxData *S) { return S->getKind() == SyntaxKind::UnknownDecl; } }; #pragma mark - unknown-declaration API class UnknownDeclSyntax : public UnknownSyntax { friend class SyntaxData; friend class UnknownStmtSyntaxData; friend class LegacyASTTransformer; using DataType = UnknownDeclSyntaxData; UnknownDeclSyntax(const RC Root, const UnknownDeclSyntaxData *Data); public: static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::UnknownDecl; } }; #pragma mark declaration-members Data class DeclMembersSyntaxData final : public SyntaxData { friend class SyntaxData; friend class DeclMembersSyntaxBuilder; friend struct SyntaxFactory; DeclMembersSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); public: static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC makeBlank(); static bool classof(const SyntaxData *S) { return S->getKind() == SyntaxKind::DeclMembers; } }; #pragma mark - #pragma mark declaration-members API class DeclMembersSyntax final : public Syntax { using DataType = DeclMembersSyntaxData; friend struct SyntaxFactory; friend class SyntaxData; friend class Syntax; friend class DeclMembersSyntaxBuilder; friend class StructDeclSyntax; DeclMembersSyntax(RC Root, const DeclMembersSyntaxData *Data); public: static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::DeclMembers; } }; #pragma mark - #pragma mark declaration-members Builder (TODO) class DeclMembersSyntaxBuilder final { RawSyntax::LayoutList MembersLayout; public: DeclMembersSyntaxBuilder &addMember(DeclSyntax Member); DeclMembersSyntax build() const; }; #pragma mark - #pragma mark struct-declaration Data class StructDeclSyntaxData final : public DeclSyntaxData { friend class SyntaxData; friend class StructDeclSyntax; friend class StructDeclSyntaxBuilder; friend struct SyntaxFactory; RC CachedWhereClause; RC CachedGenericParams; RC CachedMembers; StructDeclSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC makeBlank(); public: static bool classof(const SyntaxData *S) { return S->getKind() == SyntaxKind::StructDecl; } }; #pragma mark - struct-declaration API /// struct-declaration -> attributes? access-level-modifier? /// 'struct' struct-name /// generic-parameter-clause? type-inheritance-clause? /// generic-where-clause? /// '{' struct-members '}' /// struct-name -> identifier /// struct-members -> struct-member struct-members? /// struct-member -> declaration | compiler-control-statement class StructDeclSyntax final : public DeclSyntax { using DataType = StructDeclSyntaxData; friend struct SyntaxFactory; friend class Syntax; friend class SyntaxData; friend class StructDeclSyntaxData; friend class StructDeclSyntaxBuilder; enum class Cursor : CursorIndex { StructKeyword, Identifier, GenericParameterClause, GenericWhereClause, LeftBrace, Members, RightBrace, First = StructKeyword, Last = RightBrace, }; StructDeclSyntax(const RC Root, const StructDeclSyntaxData *Data); const StructDeclSyntaxData *getData() const { return cast(Data); } public: /// Return the 'struct' keyword attached to the declaration. RC getStructKeyword() const; /// Return a StructDeclSyntax with the given 'struct' keyword. StructDeclSyntax withStructKeyword(RC NewStructKeyword) const; /// Return the identifier of the struct. RC getIdentifier() const; /// Return a StructDeclSyntax with the given identifier. StructDeclSyntax withIdentifier(RC NewIdentifier) const; /// Return the generic parameter clause of the struct declaration. GenericParameterClauseSyntax getGenericParameterClause() const; /// Return a StructDeclSyntax with the given generic parameter clause. StructDeclSyntax withGenericParameterClause(GenericParameterClauseSyntax NewGenericParams) const; /// Return the where clause of the struct declaration. GenericWhereClauseSyntax getGenericWhereClause() const; /// Return a StructDeclSyntax with the given generic where clause. StructDeclSyntax withWhereClause(GenericWhereClauseSyntax NewWhereClause) const; /// Return the left brace '{' token of the struct declaration. RC getLeftBraceToken() const; /// Return a StructDeclSyntax with the given left brace '{' token. StructDeclSyntax withLeftBrace(RC NewLeftBrace) const; /// Return the members' syntax of the struct. DeclMembersSyntax getMembers() const; /// Return a StructDeclSyntax with the given new members. StructDeclSyntax withMembers(DeclMembersSyntax NewMembers) const; /// Return the right brace '}' token of the struct declaration. RC getRightBraceToken() const; /// Return a StructDeclSyntax with the given right brace '}' token. StructDeclSyntax withRightBrace(RC NewRightBrace) const; static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::StructDecl; } }; #pragma mark - struct-declaration Builder class StructDeclSyntaxBuilder final { RawSyntax::LayoutList StructLayout; public: StructDeclSyntaxBuilder(); StructDeclSyntaxBuilder &useStructKeyword(RC StructKeyword); StructDeclSyntaxBuilder &useIdentifier(RC Identifier); StructDeclSyntaxBuilder &useLeftBrace(RC LeftBrace); StructDeclSyntaxBuilder & useGenericParameterClause(GenericParameterClauseSyntax GenericParams); StructDeclSyntaxBuilder & useGenericWhereClause(GenericWhereClauseSyntax GenericWhereClause); StructDeclSyntaxBuilder &useMembers(DeclMembersSyntax Members); StructDeclSyntaxBuilder &useRightBrace(RC RightBrace); StructDeclSyntax build() const; }; #pragma mark - #pragma mark - type-alias Data class TypeAliasDeclSyntaxData final : public DeclSyntaxData { friend class SyntaxData; friend struct SyntaxFactory; friend class TypeAliasDeclSyntaxBuilder; TypeAliasDeclSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC makeBlank(); public: static bool classof(const SyntaxData *S) { return S->getKind() == SyntaxKind::TypeAliasDecl; } }; #pragma mark - #pragma mark - type-alias API class TypeAliasDeclSyntax final : public DeclSyntax { friend struct SyntaxFactory; friend class SyntaxData; friend class TypeAliasDeclSyntaxData; friend class TypeAliasDeclSyntaxBuilder; using DataType = TypeAliasDeclSyntaxData; enum Cursor : CursorIndex { TypeAliasKeyword, Identifier, GenericParameterClause, EqualToken, Type }; TypeAliasDeclSyntax(RC Root, const TypeAliasDeclSyntaxData *Data); public: /// Return the 'typealias' keyword for the declaration. RC getTypealiasKeyword() const { return cast(getRaw()->getChild(Cursor::TypeAliasKeyword)); } /// Return a TypeAliasDeclSyntax with the given 'typealias' keyword. TypeAliasDeclSyntax withTypeAliasKeyword(RC NewTypeAliasKeyword) const; /// Return the identifier for the declaration. RC getIdentifier() const; /// Return a TypeAliasDeclSyntax with the given identifier. TypeAliasDeclSyntax withIdentifier(RC NewIdentifier) const; /// Return the generic parameter clause of the declaration. GenericParameterClauseSyntax getGenericParameterClause() const; /// Return a TypeAliasDeclSyntax with the given generic parameter clause. TypeAliasDeclSyntax withGenericParameterClause( GenericParameterClauseSyntax NewGenericParams) const; /// Return the equal '=' token from the declaration. RC getEqualToken() const; /// Return a TypeAliasDeclSyntax with the given equal '=' token. TypeAliasDeclSyntax withEqualToken(RC NewEqualToken) const; /// Return the type syntax to which the type alias is assigned. TypeSyntax getTypeSyntax() const; /// Return a TypeAliasDeclSyntax with the given type assignment. TypeAliasDeclSyntax withTypeSyntax(TypeSyntax NewType) const; static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::TypeAliasDecl; } }; #pragma mark - type-alias Builder class TypeAliasDeclSyntaxBuilder final { RawSyntax::LayoutList TypeAliasLayout; public: TypeAliasDeclSyntaxBuilder(); TypeAliasDeclSyntaxBuilder & useTypeAliasKeyword(RC TypeAliasKeyword); TypeAliasDeclSyntaxBuilder &useIdentifier(RC Identifier); TypeAliasDeclSyntaxBuilder & useGenericParameterClause(GenericParameterClauseSyntax GenericParams); TypeAliasDeclSyntaxBuilder &useEqualToken(RC EqualToken); TypeAliasDeclSyntaxBuilder &useType(TypeSyntax ReferentType); TypeAliasDeclSyntax build() const; }; #pragma mark - function-parameter Data class FunctionParameterSyntaxData final : public SyntaxData { friend struct SyntaxFactory; friend class Syntax; friend class SyntaxData; friend class FunctionParameterSyntax; RC CachedTypeSyntax; RC CachedDefaultValue; FunctionParameterSyntaxData(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC make(RC Raw, const SyntaxData *Parent = nullptr, CursorIndex IndexInParent = 0); static RC makeBlank(); public: static bool classof(const SyntaxData *SD) { return SD->getKind() == SyntaxKind::FunctionParameter; } }; #pragma mark - function-parameter API /// parameter -> /// external-parameter-name? local-parameter-name ':' /// type '...'? '='? expression? ','? class FunctionParameterSyntax final : public Syntax { friend struct SyntaxFactory; friend class Syntax; friend class SyntaxData; friend class FunctionParameterSyntaxData; enum class Cursor : CursorIndex { ExternalName, LocalName, Colon, Type, Ellipsis, DefaultEqual, DefaultExpression, TrailingComma, }; public: using DataType = FunctionParameterSyntaxData; static constexpr SyntaxKind Kind = SyntaxKind::FunctionParameter; FunctionParameterSyntax(const RC Root, const DataType *Data) : Syntax(Root, Data) {} /// Get the external name of the parameter, if there is one. RC getExternalName() const; /// Return a FunctionParameterSyntax with the given external name. FunctionParameterSyntax withExternalName(RC NewExternalName) const; /// Return the local name of the parameter. RC getLocalName() const; /// Return a FunctionParameterSyntax with the given local name. FunctionParameterSyntax withLocalName(RC NewLocalName) const; /// Return the colon ':' token between the local name and type of the /// parameter. RC getColonToken() const; /// Return a FunctionParameterSyntax with the given colon token between /// the local name and type. FunctionParameterSyntax withColonToken(RC NewColonToken) const; /// Return the syntax for the type of this parameter. llvm::Optional getTypeSyntax() const; /// Return a FunctionParameterSyntax with the given parameter type syntax. FunctionParameterSyntax withTypeSyntax(llvm::Optional NewType) const; /// Return the equal '=' token in between the parameter type and the default /// value, if there is one. RC getEqualToken() const; /// Return a FunctionParameterSyntax with the given equal '=' token in /// between the parameter type and the default value. FunctionParameterSyntax withEqualToken(RC NewEqualToken) const; /// Return the expresion for the default value of the parameter, if there /// is one. llvm::Optional getDefaultValue() const; /// Return a FunctionParameterSyntax with the given default value. To remove /// the default value, pass llvm::None. FunctionParameterSyntax withDefaultValue(llvm::Optional NewDefaultValue) const; /// Return the trailing comma on the parameter, if there is one. RC getTrailingComma() const; /// Return a FunctionParameterSyntax with the given trailing comma. FunctionParameterSyntax withTrailingComma(RC NewTrailingComma) const; static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::FunctionParameter; } }; #pragma mark - function-parameter-list Data using FunctionParameterListSyntaxData = SyntaxCollectionData; #pragma mark - function-parameter-list API /// parameter-list -> parameteter | parameter ',' parameter-list class FunctionParameterListSyntax final : public SyntaxCollection { friend struct SyntaxFactory; friend class Syntax; friend class SyntaxData; using DataType = FunctionParameterListSyntaxData; FunctionParameterListSyntax(const RC Root, const DataType *Data) : SyntaxCollection(Root, Data) {} public: static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::FunctionParameterList; } }; #pragma mark - function-signature Data class FunctionSignatureSyntaxData final : public SyntaxData { RC CachedParameterList; RC CachedReturnTypeAttributes; RC CachedReturnTypeSyntax; public: static bool classof(const SyntaxData *SD) { return SD->getKind() == SyntaxKind::FunctionSignature; } }; #pragma mark - function-signature API /// function-signature -> /// '(' parameter-list? ')' (throws | rethrows)? '->' attributes? type class FunctionSignatureSyntax final : public Syntax { friend struct SyntaxBuilder; friend class Syntax; friend class SyntaxData; friend class FunctionSignatureSyntaxData; using DataType = FunctionSignatureSyntaxData; enum class Cursor : CursorIndex { LeftParen, ParameterList, RightParen, ThrowsOrRethrows, Arrow, ReturnTypeAttributes, ReturnType, }; public: /// Return the left parenthesis '(' token enclosing the parameter list. RC getLeftParenToken() const; /// Return a FunctionSignatureSyntax with the given left parentesis '(' token /// enclosing the parameter list. FunctionSignatureSyntax withLeftParenToken(RC NewLeftParen) const; /// Return the parameter list for this signature. FunctionParameterListSyntax getParameterList() const; /// Return the parameter list for this signature. FunctionSignatureSyntax withParameterList(FunctionParameterListSyntax NewParameterList) const; /// Return the 'throws' token in this signature if it exists. RC getThrowsToken() const; /// Return a FunctionSignatureSyntax with the given 'throws' token. FunctionSignatureSyntax withThrowsToken(RC NewThrowsToken) const; /// Return the 'rethrows' token in this signature if it exists; RC getRethrowsToken() const; /// Return a FunctionSignatureSyntax with the given 'rethrows' token. FunctionSignatureSyntax withRethrowsToken(RC NewRethrowsToken) const; /// Return the arrow '->' token for the signature. RC getArrowToken() const; /// Return a FunctionSignatureSyntax with the given arrow token FunctionSignatureSyntax withArrowToken(RC NewArrowToken) const; /// Return the return type attributes for the signature. TypeAttributesSyntax getReturnTypeAttributes() const; /// Return a FunctionSignatureSyntax with the given return type attributes. FunctionSignatureSyntax withReturnTypeAttributes(TypeAttributesSyntax NewReturnTypeAttributes) const; /// Return the syntax for the return type of the signature. TypeSyntax getReturnTypeSyntax() const; /// Return a FunctionSignatureSyntax with the given return type. FunctionSignatureSyntax withReturnTypeSyntax(TypeSyntax NewReturnType) const; /// Return the right parenthesis ')' token enclosing the parameter list. RC getRightParenToken() const; /// Return a FunctionSignatureSyntax with the given right parentesis ')' token /// enclosing the parameter list. FunctionSignatureSyntax withRightParenToken(RC NewLeftParen) const; static bool classof(const Syntax *S) { return S->getKind() == SyntaxKind::FunctionSignature; } }; } // end namespace syntax } // end namespace swift #endif // SWIFT_SYNTAX_DECLSYNTAX_H