@@ -816,6 +816,49 @@ bool ModuleDecl::isInGeneratedBuffer(SourceLoc loc) {
816
816
return file->Kind == SourceFileKind::MacroExpansion;
817
817
}
818
818
819
+ std::pair<unsigned , SourceLoc>
820
+ ModuleDecl::getOriginalLocation (SourceLoc loc) const {
821
+ assert (loc.isValid ());
822
+
823
+ SourceManager &SM = getASTContext ().SourceMgr ;
824
+ unsigned bufferID = SM.findBufferContainingLoc (loc);
825
+
826
+ SourceLoc startLoc = loc;
827
+ unsigned startBufferID = bufferID;
828
+ while (Optional<GeneratedSourceInfo> info =
829
+ SM.getGeneratedSourceInfo (bufferID)) {
830
+ switch (info->kind ) {
831
+ case GeneratedSourceInfo::ExpressionMacroExpansion:
832
+ case GeneratedSourceInfo::FreestandingDeclMacroExpansion:
833
+ case GeneratedSourceInfo::AccessorMacroExpansion:
834
+ case GeneratedSourceInfo::MemberAttributeMacroExpansion:
835
+ case GeneratedSourceInfo::MemberMacroExpansion:
836
+ case GeneratedSourceInfo::PeerMacroExpansion:
837
+ case GeneratedSourceInfo::ConformanceMacroExpansion: {
838
+ // Location was within a macro expansion, return the expansion site, not
839
+ // the insertion location.
840
+ if (info->attachedMacroCustomAttr ) {
841
+ loc = info->attachedMacroCustomAttr ->getLocation ();
842
+ } else {
843
+ ASTNode expansionNode = ASTNode::getFromOpaqueValue (info->astNode );
844
+ loc = expansionNode.getStartLoc ();
845
+ }
846
+ bufferID = SM.findBufferContainingLoc (loc);
847
+ break ;
848
+ }
849
+ case GeneratedSourceInfo::ReplacedFunctionBody:
850
+ // There's not really any "original" location for locations within
851
+ // replaced function bodies. The body is actually different code to the
852
+ // original file.
853
+ case GeneratedSourceInfo::PrettyPrinted:
854
+ // No original location, return the original buffer/location
855
+ return {startBufferID, startLoc};
856
+ }
857
+ }
858
+
859
+ return {bufferID, loc};
860
+ }
861
+
819
862
ArrayRef<SourceFile *>
820
863
PrimarySourceFilesRequest::evaluate (Evaluator &evaluator,
821
864
ModuleDecl *mod) const {
@@ -1353,14 +1396,24 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
1353
1396
return None;
1354
1397
}
1355
1398
1356
- SourceLoc Loc = D->getLoc (/* SerializedOK=*/ false );
1357
- if (Loc .isInvalid ())
1399
+ SourceLoc MainLoc = D->getLoc (/* SerializedOK=*/ false );
1400
+ if (MainLoc .isInvalid ())
1358
1401
return None;
1359
1402
1403
+ // TODO: Rather than grabbing the location of the macro expansion, we should
1404
+ // instead add the generated buffer tree - that would need to include source
1405
+ // if we want to be able to retrieve documentation within generated buffers.
1360
1406
SourceManager &SM = getASTContext ().SourceMgr ;
1361
- auto BufferID = SM.findBufferContainingLoc (Loc);
1407
+ bool InGeneratedBuffer =
1408
+ !SM.rangeContainsTokenLoc (SM.getRangeForBuffer (BufferID), MainLoc);
1409
+ if (InGeneratedBuffer) {
1410
+ int UnderlyingBufferID;
1411
+ std::tie (UnderlyingBufferID, MainLoc) =
1412
+ D->getModuleContext ()->getOriginalLocation (MainLoc);
1413
+ if (BufferID != UnderlyingBufferID)
1414
+ return None;
1415
+ }
1362
1416
1363
- ExternalSourceLocs::RawLocs Result;
1364
1417
auto setLoc = [&](ExternalSourceLocs::RawLoc &RawLoc, SourceLoc Loc) {
1365
1418
if (!Loc.isValid ())
1366
1419
return ;
@@ -1379,15 +1432,20 @@ SourceFile::getExternalRawLocsForDecl(const Decl *D) const {
1379
1432
RawLoc.Directive .Name = StringRef (VF->Name );
1380
1433
};
1381
1434
1435
+ ExternalSourceLocs::RawLocs Result;
1436
+
1382
1437
Result.SourceFilePath = SM.getIdentifierForBuffer (BufferID);
1383
- for (const auto &SRC : D->getRawComment (/* SerializedOK=*/ false ).Comments ) {
1384
- Result.DocRanges .emplace_back (ExternalSourceLocs::RawLoc (),
1385
- SRC.Range .getByteLength ());
1386
- setLoc (Result.DocRanges .back ().first , SRC.Range .getStart ());
1387
- }
1388
- setLoc (Result.Loc , D->getLoc (/* SerializedOK=*/ false ));
1389
- setLoc (Result.StartLoc , D->getStartLoc ());
1390
- setLoc (Result.EndLoc , D->getEndLoc ());
1438
+ setLoc (Result.Loc , MainLoc);
1439
+ if (!InGeneratedBuffer) {
1440
+ for (const auto &SRC : D->getRawComment (/* SerializedOK=*/ false ).Comments ) {
1441
+ Result.DocRanges .emplace_back (ExternalSourceLocs::RawLoc (),
1442
+ SRC.Range .getByteLength ());
1443
+ setLoc (Result.DocRanges .back ().first , SRC.Range .getStart ());
1444
+ }
1445
+ setLoc (Result.StartLoc , D->getStartLoc ());
1446
+ setLoc (Result.EndLoc , D->getEndLoc ());
1447
+ }
1448
+
1391
1449
return Result;
1392
1450
}
1393
1451
0 commit comments