Exclude private decls from interface token hash.

After parsing a private decl, reset the token hash state to what it was
before the decl was parsed. This way, adding a private decl or editing
its type or name will not trigger a rebuild of downstream files.

<rdar://problem/22239821> Modifying private APIs shouldn't cause dependents to recompile

Swift SVN r31358
This commit is contained in:
Chris Willmore
2015-08-20 03:43:43 +00:00
parent c33e3efe59
commit 0e326dbeeb
4 changed files with 69 additions and 0 deletions

View File

@@ -174,6 +174,36 @@ namespace {
P.markWasHandled(D);
}
};
/// An RAII type to exclude tokens contributing to private decls from the
/// interface hash of the source file. On destruct, it checks if the set of
/// attributes includes the "private" attribute; if so, it resets the MD5
/// hash of the source file to what it was when the IgnorePrivateDeclTokens
/// instance was created, thus excluding from the interface hash all tokens
/// parsed in the meantime.
struct IgnorePrivateDeclTokens {
Parser &TheParser;
DeclAttributes &Attributes;
Optional<llvm::MD5> SavedHashState;
IgnorePrivateDeclTokens(Parser &P, DeclAttributes &Attrs)
: TheParser(P), Attributes(Attrs) {
if (TheParser.IsParsingInterfaceTokens) {
SavedHashState = TheParser.SF.getInterfaceHashState();
}
}
~IgnorePrivateDeclTokens() {
if (!SavedHashState)
return;
if (auto *attr = Attributes.getAttribute<AbstractAccessibilityAttr>()) {
if (attr->getAccess() == Accessibility::Private) {
TheParser.SF.setInterfaceHashState(*SavedHashState);
}
}
}
};
}
/// \brief Main entrypoint for the parser.
@@ -1711,6 +1741,7 @@ void Parser::delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
BeginParserPosition.PreviousLoc);
skipUntil(tok::eof);
}
/// \brief Parse a single syntactic declaration and return a list of decl
/// ASTs. This can return multiple results for var decls that bind to multiple
/// values, structs that define a struct decl and a constructor, etc.
@@ -1742,6 +1773,7 @@ ParserStatus Parser::parseDecl(SmallVectorImpl<Decl*> &Entries,
StructureMarkerKind::Declaration);
DeclAttributes Attributes;
IgnorePrivateDeclTokens IgnoreTokens(*this, Attributes);
if (Tok.hasComment())
Attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange()));
bool FoundCCTokenInAttr;