| //===--- ASTPrinter.h - Class for printing the AST --------------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_AST_ASTPRINTER_H |
| #define SWIFT_AST_ASTPRINTER_H |
| |
| #include "swift/Basic/LLVM.h" |
| #include "swift/Basic/QuotedString.h" |
| #include "swift/Basic/UUID.h" |
| #include "swift/AST/Identifier.h" |
| #include "llvm/ADT/SmallString.h" |
| #include "llvm/ADT/StringRef.h" |
| #include "llvm/ADT/DenseSet.h" |
| #include "llvm/Support/raw_ostream.h" |
| #include "swift/AST/PrintOptions.h" |
| |
| namespace swift { |
| class Decl; |
| class DeclContext; |
| class DynamicSelfType; |
| class ModuleEntity; |
| class TypeDecl; |
| class EnumElementDecl; |
| class Type; |
| class TypeLoc; |
| class Pattern; |
| class ExtensionDecl; |
| class NominalTypeDecl; |
| class ValueDecl; |
| class SourceLoc; |
| enum class tok; |
| enum class AccessorKind; |
| |
| /// Describes the context in which a name is being printed, which |
| /// affects the keywords that need to be escaped. |
| enum class PrintNameContext { |
| /// Normal context |
| Normal, |
| /// Keyword context, where no keywords are escaped. |
| Keyword, |
| /// Type member context, e.g. properties or enum cases. |
| TypeMember, |
| /// Generic parameter context, where 'Self' is not escaped. |
| GenericParameter, |
| /// Class method return type, where 'Self' is not escaped. |
| ClassDynamicSelf, |
| /// Function parameter context, where keywords other than let/var/inout are |
| /// not escaped. |
| FunctionParameterExternal, |
| FunctionParameterLocal, |
| /// Tuple element context, similar to \c FunctionParameterExternal. |
| TupleElement, |
| /// Attributes, which are escaped as 'Normal', but differentiated for |
| /// the purposes of printName* callbacks. |
| Attribute, |
| }; |
| |
| /// Describes the kind of structured entity being printed. |
| /// |
| /// This includes printables with sub-structure that cannot be completely |
| /// handled by the printDeclPre/printDeclPost callbacks. |
| /// E.g. |
| /// \code |
| /// func foo(<FunctionParameter>x: Int = 2</FunctionParameter>, ...) |
| /// \endcode |
| enum class PrintStructureKind { |
| GenericParameter, |
| GenericRequirement, |
| FunctionParameter, |
| FunctionType, |
| FunctionReturnType, |
| BuiltinAttribute, |
| TupleType, |
| TupleElement, |
| NumberLiteral, |
| StringLiteral, |
| }; |
| |
| /// An abstract class used to print an AST. |
| class ASTPrinter { |
| unsigned CurrentIndentation = 0; |
| unsigned PendingNewlines = 0; |
| TypeOrExtensionDecl SynthesizeTarget; |
| |
| void printTextImpl(StringRef Text); |
| |
| public: |
| virtual ~ASTPrinter() {} |
| |
| virtual void printText(StringRef Text) = 0; |
| |
| // MARK: Callback interface. |
| |
| /// Called after the printer decides not to print D. |
| /// |
| /// Callers should use callAvoidPrintDeclPost(). |
| virtual void avoidPrintDeclPost(const Decl *D) {}; |
| /// Called before printing of a declaration. |
| /// |
| /// Callers should use callPrintDeclPre(). |
| virtual void printDeclPre(const Decl *D, Optional<BracketOptions> Bracket) {} |
| /// Called before printing at the point which would be considered the location |
| /// of the declaration (normally the name of the declaration). |
| /// |
| /// Callers should use callPrintDeclLoc(). |
| virtual void printDeclLoc(const Decl *D) {} |
| /// Called after printing the name of the declaration. |
| virtual void printDeclNameEndLoc(const Decl *D) {} |
| /// Called after printing the name of a declaration, or in the case of |
| /// functions its signature. |
| virtual void printDeclNameOrSignatureEndLoc(const Decl *D) {} |
| /// Called after finishing printing of a declaration. |
| /// |
| /// Callers should use callPrintDeclPost(). |
| virtual void printDeclPost(const Decl *D, Optional<BracketOptions> Bracket) {} |
| |
| /// Called before printing the result type of the declaration. Printer can |
| /// replace \p TL to customize the input. |
| virtual void printDeclResultTypePre(ValueDecl *VD, TypeLoc &TL) {} |
| |
| /// Called before printing a type. |
| virtual void printTypePre(const TypeLoc &TL) {} |
| /// Called after printing a type. |
| virtual void printTypePost(const TypeLoc &TL) {} |
| |
| /// Called when printing the referenced name of a type declaration, possibly |
| /// from deep inside another type. |
| /// |
| /// \param T the original \c Type being referenced. May be null. |
| /// \param RefTo the \c TypeDecl this is considered a reference to. |
| /// \param Name the name to be printed. |
| /// \param NameContext the \c PrintNameContext which this type is being |
| /// printed in, used to determine how to escape type names. |
| virtual void printTypeRef( |
| Type T, const TypeDecl *RefTo, Identifier Name, |
| PrintNameContext NameContext = PrintNameContext::Normal); |
| |
| /// Called when printing the referenced name of a module. |
| virtual void printModuleRef(ModuleEntity Mod, Identifier Name); |
| |
| /// Called before printing a synthesized extension. |
| virtual void printSynthesizedExtensionPre(const ExtensionDecl *ED, |
| TypeOrExtensionDecl NTD, |
| Optional<BracketOptions> Bracket) {} |
| |
| /// Called after printing a synthesized extension. |
| virtual void printSynthesizedExtensionPost(const ExtensionDecl *ED, |
| TypeOrExtensionDecl TargetDecl, |
| Optional<BracketOptions> Bracket) { |
| } |
| |
| /// Called before printing a structured entity. |
| /// |
| /// Callers should use callPrintStructurePre(). |
| virtual void printStructurePre(PrintStructureKind Kind, |
| const Decl *D = nullptr) {} |
| /// Called after printing a structured entity. |
| virtual void printStructurePost(PrintStructureKind Kind, |
| const Decl *D = nullptr) {} |
| |
| /// Called before printing a name in the given context. |
| virtual void printNamePre(PrintNameContext Context) {} |
| /// Called after printing a name in the given context. |
| virtual void printNamePost(PrintNameContext Context) {} |
| |
| // Helper functions. |
| |
| void printSeparator(bool &first, StringRef separator) { |
| if (first) { |
| first = false; |
| } else { |
| printTextImpl(separator); |
| } |
| } |
| |
| ASTPrinter &operator<<(StringRef Text) { |
| printTextImpl(Text); |
| return *this; |
| } |
| |
| ASTPrinter &operator<<(QuotedString s); |
| |
| ASTPrinter &operator<<(unsigned long long N); |
| ASTPrinter &operator<<(UUID UU); |
| |
| ASTPrinter &operator<<(Identifier name); |
| ASTPrinter &operator<<(DeclBaseName name); |
| ASTPrinter &operator<<(DeclName name); |
| ASTPrinter &operator<<(DeclNameRef name); |
| |
| // Special case for 'char', but not arbitrary things that convert to 'char'. |
| template <typename T> |
| typename std::enable_if<std::is_same<T, char>::value, ASTPrinter &>::type |
| operator<<(T c) { |
| return *this << StringRef(&c, 1); |
| } |
| |
| void printKeyword(StringRef name, |
| const PrintOptions &Opts, |
| StringRef Suffix = "") { |
| if (Opts.SkipUnderscoredKeywords && name.startswith("_")) |
| return; |
| assert(!name.empty() && "Tried to print empty keyword"); |
| callPrintNamePre(PrintNameContext::Keyword); |
| *this << name; |
| printNamePost(PrintNameContext::Keyword); |
| *this << Suffix; |
| } |
| |
| void printAttrName(StringRef name, bool needAt = false) { |
| callPrintNamePre(PrintNameContext::Attribute); |
| if (needAt) |
| *this << "@"; |
| *this << name; |
| printNamePost(PrintNameContext::Attribute); |
| } |
| |
| ASTPrinter &printSimpleAttr(StringRef name, bool needAt = false) { |
| callPrintStructurePre(PrintStructureKind::BuiltinAttribute); |
| printAttrName(name, needAt); |
| printStructurePost(PrintStructureKind::BuiltinAttribute); |
| return *this; |
| } |
| |
| void printEscapedStringLiteral(StringRef str); |
| |
| void printName(Identifier Name, |
| PrintNameContext Context = PrintNameContext::Normal); |
| |
| void setIndent(unsigned NumSpaces) { |
| CurrentIndentation = NumSpaces; |
| } |
| |
| void setSynthesizedTarget(TypeOrExtensionDecl Target) { |
| assert((!SynthesizeTarget || !Target || Target == SynthesizeTarget) && |
| "unexpected change of setSynthesizedTarget"); |
| // FIXME: this can overwrite the original target with nullptr. |
| SynthesizeTarget = Target; |
| } |
| |
| void printNewline() { |
| PendingNewlines++; |
| } |
| |
| void forceNewlines() { |
| if (PendingNewlines > 0) { |
| llvm::SmallString<16> Str; |
| for (unsigned i = 0; i != PendingNewlines; ++i) |
| Str += '\n'; |
| PendingNewlines = 0; |
| printText(Str); |
| printIndent(); |
| } |
| } |
| |
| virtual void printIndent(); |
| |
| // MARK: Callback interface wrappers that perform ASTPrinter bookkeeping. |
| |
| /// Make a callback to printDeclPre(), performing any necessary bookeeping. |
| void callPrintDeclPre(const Decl *D, Optional<BracketOptions> Bracket); |
| |
| /// Make a callback to printDeclPost(), performing any necessary bookeeping. |
| void callPrintDeclPost(const Decl *D, Optional<BracketOptions> Bracket) { |
| printDeclPost(D, Bracket); |
| } |
| |
| /// Make a callback to avoidPrintDeclPost(), performing any necessary |
| /// bookkeeping. |
| void callAvoidPrintDeclPost(const Decl *D) { |
| avoidPrintDeclPost(D); |
| } |
| |
| /// Make a callback to printDeclLoc(), performing any necessary bookeeping. |
| void callPrintDeclLoc(const Decl *D) { |
| forceNewlines(); |
| printDeclLoc(D); |
| } |
| |
| /// Make a callback to printNamePre(), performing any necessary bookeeping. |
| void callPrintNamePre(PrintNameContext Context) { |
| forceNewlines(); |
| printNamePre(Context); |
| } |
| |
| /// Make a callback to printStructurePre(), performing any necessary |
| /// bookkeeping. |
| void callPrintStructurePre(PrintStructureKind Kind, const Decl *D = nullptr) { |
| forceNewlines(); |
| printStructurePre(Kind, D); |
| } |
| |
| /// To sanitize a malformed utf8 string to a well-formed one. |
| static std::string sanitizeUtf8(StringRef Text); |
| |
| private: |
| virtual void anchor(); |
| }; |
| |
| /// An AST printer for a raw_ostream. |
| class StreamPrinter : public ASTPrinter { |
| protected: |
| raw_ostream &OS; |
| |
| public: |
| explicit StreamPrinter(raw_ostream &OS) : OS(OS) {} |
| |
| void printText(StringRef Text) override; |
| }; |
| |
| /// AST stream printer that adds extra indentation to each line. |
| class ExtraIndentStreamPrinter : public StreamPrinter { |
| StringRef ExtraIndent; |
| |
| public: |
| ExtraIndentStreamPrinter(raw_ostream &out, StringRef extraIndent) |
| : StreamPrinter(out), ExtraIndent(extraIndent) { } |
| |
| virtual void printIndent() override { |
| printText(ExtraIndent); |
| StreamPrinter::printIndent(); |
| } |
| }; |
| |
| void printContext(raw_ostream &os, DeclContext *dc); |
| |
| bool printRequirementStub(ValueDecl *Requirement, DeclContext *Adopter, |
| Type AdopterTy, SourceLoc TypeLoc, raw_ostream &OS); |
| |
| /// Print a keyword or punctuator directly by its kind. |
| llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, tok keyword); |
| |
| /// Get the length of a keyword or punctuator by its kind. |
| uint8_t getKeywordLen(tok keyword); |
| |
| /// Get <#code#>; |
| StringRef getCodePlaceholder(); |
| |
| /// Given an array of enum element decls, print them as case statements with |
| /// placeholders as contents. |
| void printEnumElementsAsCases( |
| llvm::DenseSet<EnumElementDecl *> &UnhandledElements, |
| llvm::raw_ostream &OS); |
| |
| void getInheritedForPrinting(const Decl *decl, const PrintOptions &options, |
| llvm::SmallVectorImpl<TypeLoc> &Results); |
| |
| StringRef getAccessorKindString(AccessorKind value); |
| } // namespace swift |
| |
| #endif // LLVM_SWIFT_AST_ASTPRINTER_H |