blob: d1cc24da360236fae998264a55d4525311845c32 [file] [log] [blame]
//===--- 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;
#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<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;
template <typename SyntaxNode>
typename SyntaxNode::DataType *getUnsafeData() const {
auto Casted = cast<typename SyntaxNode::DataType>(Data);
return const_cast<typename SyntaxNode::DataType *>(Casted);
}
public:
using DataType = SyntaxData;
Syntax(const RC<SyntaxData> Root, const SyntaxData *Data);
/// Get the kind of syntax.
SyntaxKind getKind() const;
/// Get the shared raw syntax.
RC<RawSyntax> getRaw() 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.
template <typename T>
typename T::DataType &getData() const {
assert(is<T>() && "getData<T>() node of incompatible type!");
return *reinterpret_cast<typename T::DataType *>(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, reinterpret_cast<const typename T::DataType *>(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;
/// 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) const {
return Root == Other.Root && Data == Other.Data;
}
// TODO: hasSameStructureAs ?
};
} // end namespace syntax
} // end namespace swift
#endif // SWIFT_SYNTAX_SYNTAX_H