//===--- 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/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 SyntaxNode make(RC 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 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 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. RC getRaw() const; /// 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 getChild(const size_t N) const; /// Returns true if the syntax node is of the given type. template 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 T castTo() const { assert(is() && "castTo() 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 llvm::Optional getAs() const { if (is()) { return castTo(); } return llvm::None; } /// Return the parent of this node, if it has one. llvm::Optional 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. void dump() const; 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) of this raw syntax: its offset, /// line, and column. AbsolutePosition getAbsoluteEndPosition() const { return Data->getAbsoluteEndPosition(); } /// Get the absolute position without skipping the leading trivia of this /// node. AbsolutePosition getAbsolutePositionWithLeadingTrivia() const { return Data->getAbsolutePositionWithLeadingTrivia(); } // TODO: hasSameStructureAs ? }; } // end namespace syntax } // end namespace swift #endif // SWIFT_SYNTAX_SYNTAX_H