mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -1083,6 +1083,9 @@ public:
|
|||||||
InterfaceHash.update(a);
|
InterfaceHash.update(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const llvm::MD5 &getInterfaceHashState() { return InterfaceHash; }
|
||||||
|
void setInterfaceHashState(const llvm::MD5 &state) { InterfaceHash = state; }
|
||||||
|
|
||||||
void getInterfaceHash(llvm::SmallString<32> &str) {
|
void getInterfaceHash(llvm::SmallString<32> &str) {
|
||||||
llvm::MD5::MD5Result result;
|
llvm::MD5::MD5Result result;
|
||||||
InterfaceHash.final(result);
|
InterfaceHash.final(result);
|
||||||
|
|||||||
@@ -174,6 +174,36 @@ namespace {
|
|||||||
P.markWasHandled(D);
|
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.
|
/// \brief Main entrypoint for the parser.
|
||||||
@@ -1711,6 +1741,7 @@ void Parser::delayParseFromBeginningToHere(ParserPosition BeginParserPosition,
|
|||||||
BeginParserPosition.PreviousLoc);
|
BeginParserPosition.PreviousLoc);
|
||||||
skipUntil(tok::eof);
|
skipUntil(tok::eof);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Parse a single syntactic declaration and return a list of decl
|
/// \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
|
/// ASTs. This can return multiple results for var decls that bind to multiple
|
||||||
/// values, structs that define a struct decl and a constructor, etc.
|
/// values, structs that define a struct decl and a constructor, etc.
|
||||||
@@ -1742,6 +1773,7 @@ ParserStatus Parser::parseDecl(SmallVectorImpl<Decl*> &Entries,
|
|||||||
StructureMarkerKind::Declaration);
|
StructureMarkerKind::Declaration);
|
||||||
|
|
||||||
DeclAttributes Attributes;
|
DeclAttributes Attributes;
|
||||||
|
IgnorePrivateDeclTokens IgnoreTokens(*this, Attributes);
|
||||||
if (Tok.hasComment())
|
if (Tok.hasComment())
|
||||||
Attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange()));
|
Attributes.add(new (Context) RawDocCommentAttr(Tok.getCommentRange()));
|
||||||
bool FoundCCTokenInAttr;
|
bool FoundCCTokenInAttr;
|
||||||
|
|||||||
23
test/InterfaceHash/added_private_method.swift
Normal file
23
test/InterfaceHash/added_private_method.swift
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// RUN: mkdir -p %t
|
||||||
|
// RUN: %S/../../utils/split_file.py -o %t %s
|
||||||
|
// RUN: %target-swift-frontend -dump-interface-hash %t/a.swift 2> %t/a.hash
|
||||||
|
// RUN: %target-swift-frontend -dump-interface-hash %t/b.swift 2> %t/b.hash
|
||||||
|
// RUN: cmp %t/a.hash %t/b.hash
|
||||||
|
|
||||||
|
// BEGIN a.swift
|
||||||
|
class C {
|
||||||
|
func f2() -> Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BEGIN b.swift
|
||||||
|
class C {
|
||||||
|
func f2() -> Int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
private func f3() -> Int {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
11
test/InterfaceHash/changed_private_var_type.swift
Normal file
11
test/InterfaceHash/changed_private_var_type.swift
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// RUN: mkdir -p %t
|
||||||
|
// RUN: %S/../../utils/split_file.py -o %t %s
|
||||||
|
// RUN: %target-swift-frontend -dump-interface-hash %t/a.swift 2> %t/a.hash
|
||||||
|
// RUN: %target-swift-frontend -dump-interface-hash %t/b.swift 2> %t/b.hash
|
||||||
|
// RUN: cmp %t/a.hash %t/b.hash
|
||||||
|
|
||||||
|
// BEGIN a.swift
|
||||||
|
private var x: Int
|
||||||
|
|
||||||
|
// BEGIN b.swift
|
||||||
|
private var x: Float
|
||||||
Reference in New Issue
Block a user