//===--- 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/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 { namespace sema { class Semantics; } namespace syntax { const auto NoParent = llvm::None; class SyntaxData; /// 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 SyntaxData; friend class LegacyASTTransformer; friend class sema::Semantics; using DataType = SyntaxData; #define SYNTAX(Id, Parent) friend class Id##Syntax; #include "swift/Syntax/SyntaxKinds.def" 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; template typename SyntaxNode::DataType *getUnsafeData() const { auto Casted = cast(Data); return const_cast(Casted); } public: Syntax(const RC Root, const SyntaxData *Data); /// Get the kind of syntax. SyntaxKind getKind() const; /// Get the shared raw syntax. RC getRaw() 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. template typename T::DataType &getData() const { assert(is() && "getData() node of incompatible type!"); return *reinterpret_cast(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, reinterpret_cast(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; /// Returns the child index of this node in its parent, /// if it has one, otherwise 0. CursorIndex getIndexInParent() 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 type. bool isType() const; /// Returns true if this syntax is of some "unknown" kind. bool isUnknown() const; /// Print the syntax node with full fidelity to the given output stream. void print(llvm::raw_ostream &OS) 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) { return Root == Other.Root && Data == Other.Data; } // TODO: hasSameStructureAs ? }; } // end namespace syntax } // end namespace swift #endif // SWIFT_SYNTAX_SYNTAX_H