| //===--- Syntax.h - Swift 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 Syntax type, the main public-facing classes and |
| // subclasses for dealing with Swift Syntax. |
| // |
| // Syntax types contain a strong reference to the root of the tree to keep |
| // the subtree above alive, and a weak reference to the data representing |
| // the syntax node (weak to prevent retain cycles). All significant public API |
| // are contained in Syntax and its subclasses. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SYNTAX_SYNTAX_H |
| #define SWIFT_SYNTAX_SYNTAX_H |
| |
| #include "swift/Basic/Debug.h" |
| #include "swift/Syntax/SyntaxData.h" |
| #include "swift/Syntax/References.h" |
| #include "swift/Syntax/RawSyntax.h" |
| #include "swift/Syntax/Trivia.h" |
| #include "llvm/ADT/IntrusiveRefCntPtr.h" |
| #include "llvm/ADT/Optional.h" |
| #include "llvm/Support/raw_ostream.h" |
| |
| namespace swift { |
| |
| class SyntaxASTMap; |
| |
| namespace syntax { |
| |
| struct SyntaxVisitor; |
| class SourceFileSyntax; |
| |
| template <typename SyntaxNode> |
| SyntaxNode make(RC<RawSyntax> Raw) { |
| auto Data = SyntaxData::make(Raw); |
| return { Data, Data.get() }; |
| } |
| |
| const auto NoParent = llvm::None; |
| |
| /// The main handle for syntax nodes - subclasses contain all public |
| /// structured editing APIs. |
| /// |
| /// This opaque structure holds two pieces of data: a strong reference to a |
| /// root node and a weak reference to the node itself. The node of interest can |
| /// be weakly held because the data nodes contain strong references to |
| /// their children. |
| class Syntax { |
| friend struct SyntaxFactory; |
| friend class swift::SyntaxASTMap; |
| |
| protected: |
| /// A strong reference to the root node of the tree in which this piece of |
| /// syntax resides. |
| const RC<SyntaxData> Root; |
| |
| /// A raw pointer to the data representing this syntax node. |
| /// |
| /// This is mutable for being able to set cached child members, which are |
| /// lazily created. |
| mutable const SyntaxData *Data; |
| |
| public: |
| Syntax(const RC<SyntaxData> Root, const SyntaxData *Data) |
| : Root(Root), Data(Data) { |
| assert(Data != nullptr); |
| } |
| |
| virtual ~Syntax() {} |
| |
| /// Get the kind of syntax. |
| SyntaxKind getKind() const; |
| |
| /// Get the shared raw syntax. |
| const RC<RawSyntax> &getRaw() const; |
| |
| /// Get an ID for this node that is stable across incremental parses |
| SyntaxNodeId getId() const { return getRaw()->getId(); } |
| |
| /// Get the number of child nodes in this piece of syntax, not including |
| /// tokens. |
| size_t getNumChildren() const; |
| |
| /// Get the Nth child of this piece of syntax. |
| llvm::Optional<Syntax> getChild(const size_t N) const; |
| |
| /// Returns true if the syntax node is of the given type. |
| template <typename T> |
| bool is() const { |
| return T::classof(this); |
| } |
| |
| /// Get the Data for this Syntax node. |
| const SyntaxData &getData() const { |
| return *Data; |
| } |
| |
| const SyntaxData *getDataPointer() const { |
| return Data; |
| } |
| |
| /// Cast this Syntax node to a more specific type, asserting it's of the |
| /// right kind. |
| template <typename T> |
| T castTo() const { |
| assert(is<T>() && "castTo<T>() node of incompatible type!"); |
| return T { Root, Data }; |
| } |
| |
| /// If this Syntax node is of the right kind, cast and return it, |
| /// otherwise return None. |
| template <typename T> |
| llvm::Optional<T> getAs() const { |
| if (is<T>()) { |
| return castTo<T>(); |
| } |
| return llvm::None; |
| } |
| |
| /// Return the parent of this node, if it has one. |
| llvm::Optional<Syntax> getParent() const; |
| |
| /// Return the root syntax of this node. |
| Syntax getRoot() const; |
| |
| /// Returns the child index of this node in its parent, |
| /// if it has one, otherwise 0. |
| CursorIndex getIndexInParent() const { return getData().getIndexInParent(); } |
| |
| /// Return the number of bytes this node takes when spelled out in the source |
| size_t getTextLength() const { return getRaw()->getTextLength(); } |
| |
| /// Returns true if this syntax node represents a token. |
| bool isToken() const; |
| |
| /// Returns true if this syntax node represents a statement. |
| bool isStmt() const; |
| |
| /// Returns true if this syntax node represents a declaration. |
| bool isDecl() const; |
| |
| /// Returns true if this syntax node represents an expression. |
| bool isExpr() const; |
| |
| /// Returns true if this syntax node represents a pattern. |
| bool isPattern() const; |
| |
| /// Returns true if this syntax node represents a type. |
| bool isType() const; |
| |
| /// Returns true if this syntax is of some "unknown" kind. |
| bool isUnknown() const; |
| |
| /// Returns true if the node is "missing" in the source (i.e. it was |
| /// expected (or optional) but not written. |
| bool isMissing() const; |
| |
| /// Returns true if the node is "present" in the source. |
| bool isPresent() const; |
| |
| /// Print the syntax node with full fidelity to the given output stream. |
| void print(llvm::raw_ostream &OS, SyntaxPrintOptions Opts = SyntaxPrintOptions()) const; |
| |
| /// Print a debug representation of the syntax node to the given output stream |
| /// and indentation level. |
| void dump(llvm::raw_ostream &OS, unsigned Indent = 0) const; |
| |
| /// Print a debug representation of the syntax node to standard error. |
| SWIFT_DEBUG_DUMP; |
| |
| bool hasSameIdentityAs(const Syntax &Other) const { |
| return Root == Other.Root && Data == Other.Data; |
| } |
| |
| static bool kindof(SyntaxKind Kind) { |
| return true; |
| } |
| |
| static bool classof(const Syntax *S) { |
| // Trivially true. |
| return true; |
| } |
| |
| /// Recursively visit this node. |
| void accept(SyntaxVisitor &Visitor); |
| |
| /// Get the absolute position of this raw syntax: its offset, line, |
| /// and column. |
| AbsolutePosition getAbsolutePosition() const { |
| return Data->getAbsolutePosition(); |
| } |
| |
| /// Get the absolute end position (exclusively) where the trailing trivia of |
| /// this node ends. |
| AbsolutePosition getAbsoluteEndPositionAfterTrailingTrivia() const { |
| return Data->getAbsoluteEndPositionAfterTrailingTrivia(); |
| } |
| |
| /// Get the absolute position at which the leading trivia of this node starts. |
| AbsolutePosition getAbsolutePositionBeforeLeadingTrivia() const { |
| return Data->getAbsolutePositionBeforeLeadingTrivia(); |
| } |
| |
| // TODO: hasSameStructureAs ? |
| }; |
| |
| } // end namespace syntax |
| } // end namespace swift |
| |
| #endif // SWIFT_SYNTAX_SYNTAX_H |