Files
swift-mirror/include/swift/Syntax/Syntax.h
Brent Royal-Gordon 99faa033fc [NFC] Standardize dump() methods in frontend
By convention, most structs and classes in the Swift compiler include a `dump()` method which prints debugging information. This method is meant to be called only from the debugger, but this means they’re often unused and may be eliminated from optimized binaries. On the other hand, some parts of the compiler call `dump()` methods directly despite them being intended as a pure debugging aid. clang supports attributes which can be used to avoid these problems, but they’re used very inconsistently across the compiler.

This commit adds `SWIFT_DEBUG_DUMP` and `SWIFT_DEBUG_DUMPER(<name>(<params>))` macros to declare `dump()` methods with the appropriate set of attributes and adopts this macro throughout the frontend. It does not pervasively adopt this macro in SILGen, SILOptimizer, or IRGen; these components use `dump()` methods in a different way where they’re frequently called from debugging code. Nor does it adopt it in runtime components like swiftRuntime and swiftReflection, because I’m a bit worried about size.

Despite the large number of files and lines affected, this change is NFC.
2019-10-31 18:37:42 -07:00

222 lines
6.5 KiB
C++

//===--- 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