mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[SourceKit] Support location info for macro-expanded Clang imports
Currently, when we jump-to-definition for decls that are macro-expanded
from Clang imported decls (e.g., safe overloads generated by
@_SwiftifyImport), setLocationInfo() emits a bongus location pointing to
a generated buffer, leading the IDE to try to jump to a file that does
not exist.
The root cause here is that setLocationInfo() calls getOriginalRange()
(earlier, getOriginalLocation()), which was not written to account for
such cases where a macro is generated from another generated buffer
whose kind is 'AttributeFromClang'.
This patch fixes setLocationInfo() with some refactoring:
- getOriginalRange() is inlined into setLocationInfo(), so that the
generated buffer-handling logic is localized to that function. This
includes how it handles buffers generated for ReplacedFunctionBody.
- getOriginalLocation() is used in a couple of other places that only
care about macros expanded from the same buffer (so other generated
buffers not not relevant). This "macro-chasing" logic is simplified
and moved from ModuleDecl::getOriginalRange() to a free-standing
function, getMacroUnexpandedRange() (there is no reason for it to be
a method of ModuleDecl).
- GeneratedSourceInfo now carries an extra ClangNode field, which is
populated by getClangSwiftAttrSourceFile() when constructing
a generated buffer for an 'AttributeFromClang'. This could probably
be union'ed with one or more of the other fields in the future.
rdar://151020332
(cherry picked from commit 44aba1382d)
This commit is contained in:
@@ -68,6 +68,7 @@
|
||||
#include "llvm/Support/SaveAndRestore.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include <optional>
|
||||
|
||||
using namespace swift;
|
||||
|
||||
@@ -847,49 +848,6 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<unsigned, SourceRange>
|
||||
ModuleDecl::getOriginalRange(SourceRange range) const {
|
||||
assert(range.isValid());
|
||||
|
||||
SourceManager &SM = getASTContext().SourceMgr;
|
||||
unsigned bufferID = SM.findBufferContainingLoc(range.Start);
|
||||
|
||||
auto startRange = range;
|
||||
unsigned startBufferID = bufferID;
|
||||
while (const GeneratedSourceInfo *info =
|
||||
SM.getGeneratedSourceInfo(bufferID)) {
|
||||
switch (info->kind) {
|
||||
#define MACRO_ROLE(Name, Description) \
|
||||
case GeneratedSourceInfo::Name##MacroExpansion:
|
||||
#include "swift/Basic/MacroRoles.def"
|
||||
{
|
||||
// Location was within a macro expansion, return the expansion site, not
|
||||
// the insertion location.
|
||||
if (info->attachedMacroCustomAttr) {
|
||||
range = info->attachedMacroCustomAttr->getRange();
|
||||
} else {
|
||||
ASTNode expansionNode = ASTNode::getFromOpaqueValue(info->astNode);
|
||||
range = expansionNode.getSourceRange();
|
||||
}
|
||||
bufferID = SM.findBufferContainingLoc(range.Start);
|
||||
break;
|
||||
}
|
||||
case GeneratedSourceInfo::DefaultArgument:
|
||||
// No original location as it's not actually in any source file
|
||||
case GeneratedSourceInfo::ReplacedFunctionBody:
|
||||
// There's not really any "original" location for locations within
|
||||
// replaced function bodies. The body is actually different code to the
|
||||
// original file.
|
||||
case GeneratedSourceInfo::PrettyPrinted:
|
||||
case GeneratedSourceInfo::AttributeFromClang:
|
||||
// No original location, return the original buffer/location
|
||||
return {startBufferID, startRange};
|
||||
}
|
||||
}
|
||||
|
||||
return {bufferID, range};
|
||||
}
|
||||
|
||||
ArrayRef<SourceFile *>
|
||||
PrimarySourceFilesRequest::evaluate(Evaluator &evaluator,
|
||||
ModuleDecl *mod) const {
|
||||
@@ -1431,11 +1389,11 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
|
||||
bool InGeneratedBuffer =
|
||||
!SM.rangeContainsTokenLoc(SM.getRangeForBuffer(BufferID), MainLoc);
|
||||
if (InGeneratedBuffer) {
|
||||
unsigned UnderlyingBufferID;
|
||||
std::tie(UnderlyingBufferID, MainLoc) =
|
||||
D->getModuleContext()->getOriginalLocation(MainLoc);
|
||||
if (BufferID != UnderlyingBufferID)
|
||||
return std::nullopt;
|
||||
if (auto R = getUnexpandedMacroRange(SM, MainLoc)) {
|
||||
if (BufferID != SM.findBufferContainingLoc(R.Start))
|
||||
return std::nullopt;
|
||||
MainLoc = R.Start;
|
||||
}
|
||||
}
|
||||
|
||||
auto setLoc = [&](ExternalSourceLocs::RawLoc &RawLoc, SourceLoc Loc) {
|
||||
|
||||
Reference in New Issue
Block a user