@@ -514,6 +514,123 @@ void ModuleDecl::addFile(FileUnit &newFile) {
514514 clearLookupCache ();
515515}
516516
517+ void ModuleDecl::addAuxiliaryFile (SourceFile &sourceFile) {
518+ AuxiliaryFiles.push_back (&sourceFile);
519+ }
520+
521+ namespace {
522+ // / Compare the source location ranges for two files, as an ordering to
523+ // / use for fast searches.
524+ struct SourceFileRangeComparison {
525+ SourceManager *sourceMgr;
526+
527+ bool operator ()(SourceFile *lhs, SourceFile *rhs) const {
528+ auto lhsRange = sourceMgr->getRangeForBuffer (*lhs->getBufferID ());
529+ auto rhsRange = sourceMgr->getRangeForBuffer (*rhs->getBufferID ());
530+
531+ std::less<const char *> pointerCompare;
532+ return pointerCompare (
533+ (const char *)lhsRange.getStart ().getOpaquePointerValue (),
534+ (const char *)rhsRange.getStart ().getOpaquePointerValue ());
535+ }
536+
537+ bool operator ()(SourceFile *lhs, SourceLoc rhsLoc) const {
538+ auto lhsRange = sourceMgr->getRangeForBuffer (*lhs->getBufferID ());
539+
540+ std::less<const char *> pointerCompare;
541+ return pointerCompare (
542+ (const char *)lhsRange.getEnd ().getOpaquePointerValue (),
543+ (const char *)rhsLoc.getOpaquePointerValue ());
544+ }
545+
546+ bool operator ()(SourceLoc lhsLoc, SourceFile *rhs) const {
547+ auto rhsRange = sourceMgr->getRangeForBuffer (*rhs->getBufferID ());
548+
549+ std::less<const char *> pointerCompare;
550+ return pointerCompare (
551+ (const char *)lhsLoc.getOpaquePointerValue (),
552+ (const char *)rhsRange.getEnd ().getOpaquePointerValue ());
553+ }
554+ };
555+ }
556+
557+ class swift ::ModuleSourceFileLocationMap {
558+ public:
559+ unsigned numFiles = 0 ;
560+ unsigned numAuxiliaryFiles = 0 ;
561+ std::vector<SourceFile *> allSourceFiles;
562+ };
563+
564+ void ModuleDecl::updateSourceFileLocationMap () {
565+ // Allocate a source file location map, if we don't have one already.
566+ if (!sourceFileLocationMap) {
567+ ASTContext &ctx = getASTContext ();
568+ sourceFileLocationMap = ctx.Allocate <ModuleSourceFileLocationMap>();
569+ ctx.addCleanup ([sourceFileLocationMap=sourceFileLocationMap]() {
570+ sourceFileLocationMap->~ModuleSourceFileLocationMap ();
571+ });
572+ }
573+
574+ // If we are up-to-date, there's nothing to do.
575+ if (sourceFileLocationMap->numFiles == getFiles ().size () &&
576+ sourceFileLocationMap->numAuxiliaryFiles ==
577+ AuxiliaryFiles.size ())
578+ return ;
579+
580+ // Rebuild the range structure.
581+ sourceFileLocationMap->allSourceFiles .clear ();
582+
583+ // First, add all of the source files with a backing buffer.
584+ for (auto *fileUnit : getFiles ()) {
585+ if (auto sourceFile = dyn_cast<SourceFile>(fileUnit)) {
586+ if (sourceFile->getBufferID ())
587+ sourceFileLocationMap->allSourceFiles .push_back (sourceFile);
588+ }
589+ }
590+
591+ // Next, add all of the macro expansion files.
592+ for (auto *sourceFile : AuxiliaryFiles)
593+ sourceFileLocationMap->allSourceFiles .push_back (sourceFile);
594+
595+ // Finally, sort them all so we can do a binary search for lookup.
596+ std::sort (sourceFileLocationMap->allSourceFiles .begin (),
597+ sourceFileLocationMap->allSourceFiles .end (),
598+ SourceFileRangeComparison{&getASTContext ().SourceMgr });
599+ }
600+
601+ SourceFile *ModuleDecl::getSourceFileContainingLocation (SourceLoc loc) {
602+ if (loc.isInvalid ())
603+ return nullptr ;
604+
605+ SourceLoc adjustedLoc = loc;
606+
607+ // Check whether this location is in a "replaced" range, in which case
608+ // we want to use the original source file.
609+ auto &sourceMgr = getASTContext ().SourceMgr ;
610+ for (const auto &pair : sourceMgr.getReplacedRanges ()) {
611+ if (sourceMgr.rangeContainsTokenLoc (pair.second , loc)) {
612+ adjustedLoc = pair.first .Start ;
613+ break ;
614+ }
615+ }
616+ updateSourceFileLocationMap ();
617+
618+ auto found = std::lower_bound (sourceFileLocationMap->allSourceFiles .begin (),
619+ sourceFileLocationMap->allSourceFiles .end (),
620+ adjustedLoc,
621+ SourceFileRangeComparison{&sourceMgr});
622+ if (found == sourceFileLocationMap->allSourceFiles .end ())
623+ return nullptr ;
624+
625+ auto foundSourceFile = *found;
626+ auto foundRange = sourceMgr.getRangeForBuffer (*foundSourceFile->getBufferID ());
627+ if (!foundRange.contains (adjustedLoc))
628+ return nullptr ;
629+
630+
631+ return foundSourceFile;
632+ }
633+
517634ArrayRef<SourceFile *>
518635PrimarySourceFilesRequest::evaluate (Evaluator &evaluator,
519636 ModuleDecl *mod) const {
@@ -747,6 +864,14 @@ void SourceFile::lookupClassMembers(ImportPath::Access accessPath,
747864 cache.lookupClassMembers (accessPath, consumer);
748865}
749866
867+ SourceFile *SourceFile::getEnclosingSourceFile () const {
868+ if (Kind != SourceFileKind::MacroExpansion)
869+ return nullptr ;
870+
871+ auto sourceLoc = macroExpansion.getStartLoc ();
872+ return getParentModule ()->getSourceFileContainingLocation (sourceLoc);
873+ }
874+
750875void ModuleDecl::lookupClassMember (ImportPath::Access accessPath,
751876 DeclName name,
752877 SmallVectorImpl<ValueDecl*> &results) const {
@@ -3075,19 +3200,26 @@ ModuleDecl::computeFileIDMap(bool shouldDiagnose) const {
30753200
30763201SourceFile::SourceFile (ModuleDecl &M, SourceFileKind K,
30773202 Optional<unsigned > bufferID,
3078- ParsingOptions parsingOpts, bool isPrimary)
3203+ ParsingOptions parsingOpts, bool isPrimary,
3204+ ASTNode macroExpansion)
30793205 : FileUnit(FileUnitKind::Source, M), BufferID(bufferID ? *bufferID : -1 ),
3080- ParsingOpts(parsingOpts), IsPrimary(isPrimary), Kind(K) {
3206+ ParsingOpts(parsingOpts), IsPrimary(isPrimary),
3207+ macroExpansion(macroExpansion), Kind(K) {
30813208 M.getASTContext ().addDestructorCleanup (*this );
30823209
30833210 assert (!IsPrimary || M.isMainModule () &&
30843211 " A primary cannot appear outside the main module" );
3212+ assert (macroExpansion.isNull () == (K != SourceFileKind::MacroExpansion) &&
3213+ " Macro expansions always need an expansion node" );
30853214
30863215 if (isScriptMode ()) {
30873216 bool problem = M.registerEntryPointFile (this , SourceLoc (), None);
30883217 assert (!problem && " multiple main files?" );
30893218 (void )problem;
30903219 }
3220+
3221+ if (Kind == SourceFileKind::MacroExpansion)
3222+ M.addAuxiliaryFile (*this );
30913223}
30923224
30933225SourceFile::ParsingOptions
0 commit comments