blob: 31fac98aa9a16b725f6fd3fa082a01555ab9afd5 [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/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;
class TokenSyntax;
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;
/// Returns the first non-missing token in this syntax. Returns None if there
/// is no non-missing token.
Optional<TokenSyntax> getFirstToken() const;
/// Returns the last non-missing token in this syntax. Returns None if there
/// is no non-missing token.
Optional<TokenSyntax> getLastToken() 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) 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