[ASTPrinter] Enforce pairing of pre/post decl callbacks

We can have multiple printDeclPre callbacks pending (e.g top-level-code
decls), so use a vector to ensure we don't lose the earlier callbacks.

We also may end up calling printDeclPost without forcing the
corresponding printDeclPre first if the decl doesn't actually print
anything (e.g. an if-config statement when skipping those). So add a
wrapper callPrintDeclPost that can check for this and skip both
callbacks.  In theory, we could handle this case by instead making all
ast nodes go through something like shouldPrint() and making an
invariant that something will be printed if and only if shouldPrint
returns true.  However, that is not an obvious win, because it forces us
to walk all the first-level statements and decls inside a top-level-code
decl to determine if anything will be printed, and it also means we can
never make local decisions about whether something will be printed.  For
now, I've chosen to maintain flexibility by recovering from unprinted
decls.

Finally, add a bunch of assertions to try to keep callbacks sane.
This commit is contained in:
Ben Langmuir
2016-02-29 12:37:50 -08:00
parent e7738bbdde
commit f0d306eb10
3 changed files with 61 additions and 20 deletions

View File

@@ -420,7 +420,7 @@ void swift::ide::printSubmoduleInterface(
auto PrintDecl = [&](Decl *D) -> bool {
ASTPrinter &Printer = *PrinterToUse;
if (!shouldPrint(D, AdjustedOptions)) {
Printer.avoidPrintDeclPost(D);
Printer.callAvoidPrintDeclPost(D);
return false;
}
if (auto Ext = dyn_cast<ExtensionDecl>(D)) {
@@ -451,7 +451,7 @@ void swift::ide::printSubmoduleInterface(
// Print Ext and add sub-types of Ext.
for (auto Ext : NTD->getExtensions()) {
if (!shouldPrint(Ext, AdjustedOptions)) {
Printer.avoidPrintDeclPost(Ext);
Printer.callAvoidPrintDeclPost(Ext);
continue;
}
if (Ext->hasClangNode())
@@ -618,7 +618,7 @@ void swift::ide::printHeaderInterface(
for (auto *D : ClangDecls) {
ASTPrinter &Printer = *PrinterToUse;
if (!shouldPrint(D, AdjustedOptions)) {
Printer.avoidPrintDeclPost(D);
Printer.callAvoidPrintDeclPost(D);
continue;
}
if (D->print(Printer, AdjustedOptions))