Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion include/swift/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -4975,7 +4975,10 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
TypeChecked,

/// This is a memberwise initializer that will be synthesized by SILGen.
MemberwiseInitializer
MemberwiseInitializer,

/// Function body text was deserialized from a .swiftmodule.
Deserialized

// This enum currently needs to fit in a 3-bit bitfield.
};
Expand All @@ -4997,6 +5000,9 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
/// BodyKind::TypeChecked.
BraceStmt *Body;

/// This enum member is active if getBodyKind() is BodyKind::Deserialized.
StringRef BodyStringRepresentation;

/// This enum member is active if getBodyKind() == BodyKind::Synthesize.
BodySynthesizer Synthesizer;

Expand Down Expand Up @@ -5091,6 +5097,11 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
return getBodyKind() != BodyKind::None;
}

/// Returns true if the text of this function's body can be retrieved either
/// by extracting the text from the source buffer or reading the inlinable
/// body from a deserialized swiftmodule.
bool hasInlinableBodyText() const;

/// Returns the function body, if it was parsed, or nullptr otherwise.
///
/// Note that a null return value does not imply that the source code did not
Expand Down Expand Up @@ -5154,6 +5165,18 @@ class AbstractFunctionDecl : public GenericContext, public ValueDecl {
setBodyKind(BodyKind::TypeChecked);
}

/// Gets the body of this function, stripping the unused portions of #if
/// configs inside the body. If this function was not deserialized from a
/// .swiftmodule, this body is reconstructed from the original
/// source buffer.
StringRef getInlinableBodyText(SmallVectorImpl<char> &scratch) const;

void setBodyStringRepresentation(StringRef body) {
assert(getBodyKind() == BodyKind::None);
setBodyKind(BodyKind::Deserialized);
BodyStringRepresentation = body;
}

bool isBodyTypeChecked() const {
return getBodyKind() == BodyKind::TypeChecked;
}
Expand Down
8 changes: 4 additions & 4 deletions include/swift/AST/PrintOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <vector>

namespace swift {
class ASTPrinter;
class GenericEnvironment;
class CanType;
class Decl;
Expand Down Expand Up @@ -356,10 +357,9 @@ struct PrintOptions {
QualifyNestedDeclarations ShouldQualifyNestedDeclarations =
QualifyNestedDeclarations::Never;

/// \brief If this is not \c nullptr then functions (including accessors and
/// constructors) will be printed with a body that is determined by this
/// function.
std::function<std::string(const ValueDecl *)> FunctionBody;
/// \brief If this is not \c nullptr then function bodies (including accessors
/// and constructors) will be printed by this function.
std::function<void(const ValueDecl *, ASTPrinter &)> FunctionBody;

BracketOptions BracketOptions;

Expand Down
1 change: 1 addition & 0 deletions include/swift/Serialization/DeclTypeRecordNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ OTHER(NORMAL_PROTOCOL_CONFORMANCE_ID, 246)
OTHER(PROTOCOL_CONFORMANCE_XREF, 247)
OTHER(MEMBERS, 248)
OTHER(XREF, 249)
OTHER(INLINABLE_BODY_TEXT, 250)

#undef RECORD
#undef DECLTYPERECORDNODES_HAS_RECORD_VAL
Expand Down
3 changes: 3 additions & 0 deletions include/swift/Serialization/ModuleFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,9 @@ class ModuleFile

/// Reads a foreign error conformance from \c DeclTypeCursor, if present.
Optional<ForeignErrorConvention> maybeReadForeignErrorConvention();

/// Reads inlinable body text from \c DeclTypeCursor, if present.
Optional<StringRef> maybeReadInlinableBodyText();
};

} // end namespace swift
Expand Down
19 changes: 16 additions & 3 deletions include/swift/Serialization/ModuleFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ const uint16_t VERSION_MAJOR = 0;
/// describe what change you made. The content of this comment isn't important;
/// it just ensures a conflict if two people change the module format.
/// Don't worry about adhering to the 80-column limit for this line.
const uint16_t VERSION_MINOR = 443; // Last change: serialize unsubstituted type alias type
const uint16_t VERSION_MINOR = 444; // Last change: inlinable body text

using DeclIDField = BCFixed<31>;

Expand Down Expand Up @@ -979,8 +979,11 @@ namespace decls_block {
BCVBR<5>, // number of parameter name components
BCArray<IdentifierIDField> // name components,
// followed by TypeID dependencies
// Trailed by its generic parameters, if any, followed by the parameter
// patterns.
// This record is trailed by:
// - its generic parameters, if any
// - its parameter patterns,
// - the foreign error convention, if any
// - inlinable body text, if any
>;

using VarLayout = BCRecordLayout<
Expand Down Expand Up @@ -1044,6 +1047,8 @@ namespace decls_block {
// - its _silgen_name, if any
// - its generic parameters, if any
// - body parameter patterns
// - the foreign error convention, if any
// - inlinable body text, if any
>;

// TODO: remove the unnecessary FuncDecl components here
Expand Down Expand Up @@ -1073,6 +1078,8 @@ namespace decls_block {
// - its _silgen_name, if any
// - its generic parameters, if any
// - body parameter patterns
// - the foreign error convention, if any
// - inlinable body text, if any
>;

using PatternBindingLayout = BCRecordLayout<
Expand Down Expand Up @@ -1176,6 +1183,12 @@ namespace decls_block {
BCFixed<1>, // implicit?
BCFixed<1>, // objc?
GenericEnvironmentIDField // generic environment
// This record is trailed by its inlinable body text
>;

using InlinableBodyTextLayout = BCRecordLayout<
INLINABLE_BODY_TEXT,
BCBlob // body text
>;

using ParameterListLayout = BCRecordLayout<
Expand Down
139 changes: 67 additions & 72 deletions lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,15 @@ PrintOptions PrintOptions::printTextualInterfaceFile() {
result.SkipImports = true;
result.OmitNameOfInaccessibleProperties = true;

result.FunctionBody = [](const ValueDecl *decl, ASTPrinter &printer) {
auto AFD = dyn_cast<AbstractFunctionDecl>(decl);
if (!AFD || !AFD->hasInlinableBodyText()) return;
if (AFD->getResilienceExpansion() != ResilienceExpansion::Minimal)
return;
SmallString<128> scratch;
printer << " " << AFD->getInlinableBodyText(scratch);
};

class ShouldPrintForTextualInterface : public ShouldPrintChecker {
bool shouldPrint(const Decl *D, const PrintOptions &options) override {
// Skip anything that isn't 'public' or '@usableFromInline'.
Expand Down Expand Up @@ -645,6 +654,7 @@ class PrintAST : public ASTVisitor<PrintAST> {

void printAttributes(const Decl *D);
void printTypedPattern(const TypedPattern *TP);
void printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty = true);

public:
void printPattern(const Pattern *pattern);
Expand Down Expand Up @@ -686,6 +696,7 @@ class PrintAST : public ASTVisitor<PrintAST> {
void printGenericDeclGenericParams(GenericContext *decl);
void printGenericDeclGenericRequirements(GenericContext *decl);
void printInherited(const Decl *decl);
void printBodyIfNecessary(const AbstractFunctionDecl *decl);

void printEnumElement(EnumElementDecl *elt);

Expand Down Expand Up @@ -1471,6 +1482,29 @@ bool PrintAST::shouldPrint(const Decl *D, bool Notify) {
return Result;
}

void PrintAST::printBraceStmt(const BraceStmt *stmt, bool newlineIfEmpty) {
Printer << "{";
if (printASTNodes(stmt->getElements()) || newlineIfEmpty) {
Printer.printNewline();
indent();
}
Printer << "}";
}

void PrintAST::printBodyIfNecessary(const AbstractFunctionDecl *decl) {
if (auto BodyFunc = Options.FunctionBody) {
BodyFunc(decl, Printer);
indent();
return;
}

if (!Options.FunctionDefinitions || !decl->getBody())
return;

Printer << " ";
printBraceStmt(decl->getBody(), /*newlineIfEmpty*/!isa<AccessorDecl>(decl));
}

static bool isAccessorAssumedNonMutating(AccessorKind kind) {
switch (kind) {
case AccessorKind::Get:
Expand Down Expand Up @@ -1630,26 +1664,37 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
Printer << " ";
Printer.printKeyword(getAccessorLabel(Accessor));
} else {
Printer.printNewline();
IndentRAII IndentMore(*this);
{
IndentRAII IndentMore(*this);
indent();
visit(Accessor);
}
indent();
visit(Accessor);
Printer.printNewline();
}
};

Printer << " {";
if ((PrintAbstract ||
(impl.getReadImpl() == ReadImplKind::Get && ASD->getGetter())) &&
!ASD->supportsMutation() && !ASD->isGetterMutating() &&
PrintAccessorBody && !Options.FunctionDefinitions) {
// Omit the 'get' keyword. Directly print getter
if (auto BodyFunc = Options.FunctionBody) {
Printer.printNewline();
IndentRAII IndentBody(*this);
BodyFunc(ASD->getGetter(), Printer);
indent();
Printer << BodyFunc(ASD->getGetter());
return;
}
} else if (PrintAbstract) {
Printer.printNewline();
indent();
return;
}

Printer << " {";

if (PrintAccessorBody)
Printer.printNewline();

if (PrintAbstract) {
PrintAccessor(ASD->getGetter());
if (ASD->supportsMutation())
PrintAccessor(ASD->getSetter());
Expand Down Expand Up @@ -1693,12 +1738,16 @@ void PrintAST::printAccessors(AbstractStorageDecl *ASD) {
break;
}
}
if (PrintAccessorBody) {
Printer.printNewline();
indent();
} else

if (!PrintAccessorBody)
Printer << " ";

Printer << "}";

if (!PrintAbstract)
Printer.printNewline();

indent();
}

void PrintAST::printMembersOfDecl(Decl *D, bool needComma,
Expand Down Expand Up @@ -2497,7 +2546,6 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
[&]{
Printer << getAccessorLabel(decl);
});
Printer << " {";
break;
case AccessorKind::Set:
case AccessorKind::WillSet:
Expand All @@ -2515,24 +2563,9 @@ void PrintAST::visitAccessorDecl(AccessorDecl *decl) {
}
}
});
Printer << " {";
}
if (auto BodyFunc = Options.FunctionBody) {
{
IndentRAII IndentBody(*this);
indent();
Printer.printNewline();
Printer << BodyFunc(decl);
}
indent();
Printer.printNewline();
} else if (Options.FunctionDefinitions && decl->getBody()) {
if (printASTNodes(decl->getBody()->getElements())) {
Printer.printNewline();
indent();
}
}
Printer << "}";

printBodyIfNecessary(decl);
}

void PrintAST::visitFuncDecl(FuncDecl *decl) {
Expand Down Expand Up @@ -2604,22 +2637,7 @@ void PrintAST::visitFuncDecl(FuncDecl *decl) {
printGenericDeclGenericRequirements(decl);
}

if (auto BodyFunc = Options.FunctionBody) {
Printer << " {";
Printer.printNewline();
{
IndentRAII IndentBody(*this);
indent();
Printer << BodyFunc(decl);
}
indent();
Printer.printNewline();
Printer << "}";

} else if (Options.FunctionDefinitions && decl->getBody()) {
Printer << " ";
visit(decl->getBody());
}
printBodyIfNecessary(decl);
}

void PrintAST::printEnumElement(EnumElementDecl *elt) {
Expand Down Expand Up @@ -2788,21 +2806,7 @@ void PrintAST::visitConstructorDecl(ConstructorDecl *decl) {

printGenericDeclGenericRequirements(decl);

if (auto BodyFunc = Options.FunctionBody) {
Printer << " {";
{
Printer.printNewline();
IndentRAII IndentBody(*this);
indent();
Printer << BodyFunc(decl);
}
indent();
Printer.printNewline();
Printer << "}";
} else if (Options.FunctionDefinitions && decl->getBody()) {
Printer << " ";
visit(decl->getBody());
}
printBodyIfNecessary(decl);
}

void PrintAST::visitDestructorDecl(DestructorDecl *decl) {
Expand All @@ -2814,12 +2818,7 @@ void PrintAST::visitDestructorDecl(DestructorDecl *decl) {
Printer << "deinit";
});

if (!Options.FunctionDefinitions || !decl->getBody()) {
return;
}

Printer << " ";
visit(decl->getBody());
printBodyIfNecessary(decl);
}

void PrintAST::visitInfixOperatorDecl(InfixOperatorDecl *decl) {
Expand Down Expand Up @@ -2929,11 +2928,7 @@ void PrintAST::visitMissingMemberDecl(MissingMemberDecl *decl) {
}

void PrintAST::visitBraceStmt(BraceStmt *stmt) {
Printer << "{";
printASTNodes(stmt->getElements());
Printer.printNewline();
indent();
Printer << "}";
printBraceStmt(stmt);
}

void PrintAST::visitReturnStmt(ReturnStmt *stmt) {
Expand Down
1 change: 1 addition & 0 deletions lib/AST/ASTVerifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ class Verifier : public ASTWalker {
case AbstractFunctionDecl::BodyKind::TypeChecked:
case AbstractFunctionDecl::BodyKind::Skipped:
case AbstractFunctionDecl::BodyKind::MemberwiseInitializer:
case AbstractFunctionDecl::BodyKind::Deserialized:
return true;

case AbstractFunctionDecl::BodyKind::Unparsed:
Expand Down
Loading