mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
* spelling: accessor Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: accommodates Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: argument Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: associated Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: availability Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: available Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: belongs Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: bookkeeping Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: building Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: clazz Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: clonable Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: closure Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: concatenated Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: conformance Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: context Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: conversion Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: correspondence Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: declarations Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: declared Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: defining Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: delayed Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: dependency Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: deployed Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: descendants Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: diagnose Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: diagnostic Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: equitable Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: evaluation Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: exclusivity Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: existence Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: existential Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: explicit Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: expressed Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: for Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: foreign Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: function Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: identifier Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: implicit Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: indices Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: information Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: instance Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: interchangeable Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: interface Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: introduced Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: invalid Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: kind-in Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: least Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: library Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: location Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: namespace Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: necessary Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: nonexistent Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: not Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: number Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: obtains Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: occurs Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: opaque Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: overridden Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: parameter Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: precede Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: preceding Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: property Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: protocol Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: qualified Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: recognized Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: recursively Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: references Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: relaxing Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: represented Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: request Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: requirement Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: requirements Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: retrieve Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: returned Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: satisfied Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: satisfy Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: scanner Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: siblings Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: simplified Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: something Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: source Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: specializations Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: specially Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: statement Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: stripped Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: structure Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: substitution Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: the Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: transform Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: transformed Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: transitively Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: transparent Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: typecheck Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: unknown Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: unlabeled Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: unqualified Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: whether Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: with Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> * spelling: scanner Signed-off-by: Josh Soref <jsoref@users.noreply.github.com> Co-authored-by: Josh Soref <jsoref@users.noreply.github.com>
162 lines
6.5 KiB
C++
162 lines
6.5 KiB
C++
//===----------------------- SearchPathOptions.cpp ------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2014 - 2021 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "swift/AST/SearchPathOptions.h"
|
|
#include "llvm/ADT/SmallSet.h"
|
|
#include "llvm/Support/Errc.h"
|
|
|
|
using namespace swift;
|
|
|
|
void ModuleSearchPathLookup::addFilesInPathToLookupTable(
|
|
llvm::vfs::FileSystem *FS, StringRef SearchPath, ModuleSearchPathKind Kind,
|
|
bool IsSystem, unsigned SearchPathIndex) {
|
|
std::error_code Error;
|
|
auto entryAlreadyExists = [this](ModuleSearchPathKind Kind,
|
|
unsigned SearchPathIndex) -> bool {
|
|
return llvm::any_of(LookupTable, [&](const auto &LookupTableEntry) {
|
|
return llvm::any_of(
|
|
LookupTableEntry.second, [&](ModuleSearchPathPtr ExistingSearchPath) {
|
|
return ExistingSearchPath->getKind() == Kind &&
|
|
ExistingSearchPath->getIndex() == SearchPathIndex;
|
|
});
|
|
});
|
|
};
|
|
assert(!entryAlreadyExists(Kind, SearchPathIndex) &&
|
|
"Search path with this kind and index already exists");
|
|
ModuleSearchPathPtr TableEntry =
|
|
new ModuleSearchPath(SearchPath, Kind, IsSystem, SearchPathIndex);
|
|
for (auto Dir = FS->dir_begin(SearchPath, Error);
|
|
!Error && Dir != llvm::vfs::directory_iterator(); Dir.increment(Error)) {
|
|
StringRef Filename = llvm::sys::path::filename(Dir->path());
|
|
LookupTable[Filename].push_back(TableEntry);
|
|
}
|
|
}
|
|
|
|
void ModuleSearchPathLookup::rebuildLookupTable(const SearchPathOptions *Opts,
|
|
llvm::vfs::FileSystem *FS,
|
|
bool IsOSDarwin) {
|
|
clearLookupTable();
|
|
|
|
for (auto Entry : llvm::enumerate(Opts->getImportSearchPaths())) {
|
|
addFilesInPathToLookupTable(FS, Entry.value(),
|
|
ModuleSearchPathKind::Import,
|
|
/*isSystem=*/false, Entry.index());
|
|
}
|
|
|
|
for (auto Entry : llvm::enumerate(Opts->getFrameworkSearchPaths())) {
|
|
addFilesInPathToLookupTable(FS, Entry.value().Path, ModuleSearchPathKind::Framework,
|
|
Entry.value().IsSystem, Entry.index());
|
|
}
|
|
|
|
// Apple platforms have extra implicit framework search paths:
|
|
// $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/.
|
|
if (IsOSDarwin) {
|
|
for (auto Entry : llvm::enumerate(Opts->getDarwinImplicitFrameworkSearchPaths())) {
|
|
addFilesInPathToLookupTable(FS, Entry.value(),
|
|
ModuleSearchPathKind::DarwinImplicitFramework,
|
|
/*isSystem=*/true, Entry.index());
|
|
}
|
|
}
|
|
|
|
for (auto Entry : llvm::enumerate(Opts->getRuntimeLibraryImportPaths())) {
|
|
addFilesInPathToLookupTable(FS, Entry.value(),
|
|
ModuleSearchPathKind::RuntimeLibrary,
|
|
/*isSystem=*/true, Entry.index());
|
|
}
|
|
State.FileSystem = FS;
|
|
State.IsOSDarwin = IsOSDarwin;
|
|
State.Opts = Opts;
|
|
State.IsPopulated = true;
|
|
}
|
|
|
|
SmallVector<const ModuleSearchPath *, 4>
|
|
ModuleSearchPathLookup::searchPathsContainingFile(
|
|
const SearchPathOptions *Opts, llvm::ArrayRef<std::string> Filenames,
|
|
llvm::vfs::FileSystem *FS, bool IsOSDarwin) {
|
|
if (!State.IsPopulated || State.FileSystem != FS ||
|
|
State.IsOSDarwin != IsOSDarwin || State.Opts != Opts) {
|
|
rebuildLookupTable(Opts, FS, IsOSDarwin);
|
|
}
|
|
|
|
// Gather all search paths that include a file whose name is in Filenames.
|
|
// To make sure that we don't include the same search paths twice, keep track
|
|
// of which search paths have already been added to Result by their kind and
|
|
// Index in ResultIds.
|
|
// Note that if a search path is specified twice by including it twice in
|
|
// compiler arguments or by specifying it as different kinds (e.g. once as
|
|
// import and once as framework search path), these search paths are
|
|
// considered different (because they have different indices/kinds and may
|
|
// thus still be included twice.
|
|
llvm::SmallVector<const ModuleSearchPath *, 4> Result;
|
|
llvm::SmallSet<std::pair<ModuleSearchPathKind, unsigned>, 4> ResultIds;
|
|
|
|
for (auto &Filename : Filenames) {
|
|
for (auto &Entry : LookupTable[Filename]) {
|
|
if (ResultIds.insert(std::make_pair(Entry->getKind(), Entry->getIndex()))
|
|
.second) {
|
|
Result.push_back(Entry.get());
|
|
}
|
|
}
|
|
}
|
|
|
|
// Make sure we maintain the same search paths order that we had used in
|
|
// populateLookupTableIfNecessary after merging results from
|
|
// different filenames.
|
|
llvm::sort(Result, [](const ModuleSearchPath *Lhs,
|
|
const ModuleSearchPath *Rhs) { return *Lhs < *Rhs; });
|
|
return Result;
|
|
}
|
|
|
|
/// Loads a VFS YAML file located at \p File using \p BaseFS and adds it to
|
|
/// \p OverlayFS. Returns an error if either loading the \p File failed or it
|
|
/// is invalid.
|
|
static llvm::Error loadAndValidateVFSOverlay(
|
|
const std::string &File,
|
|
const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &BaseFS,
|
|
const llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> &OverlayFS) {
|
|
auto Buffer = BaseFS->getBufferForFile(File);
|
|
if (!Buffer)
|
|
return llvm::createFileError(File, Buffer.getError());
|
|
|
|
auto VFS = llvm::vfs::getVFSFromYAML(std::move(Buffer.get()), nullptr, File);
|
|
if (!VFS)
|
|
return llvm::createFileError(File, llvm::errc::invalid_argument);
|
|
|
|
OverlayFS->pushOverlay(std::move(VFS));
|
|
return llvm::Error::success();
|
|
}
|
|
|
|
llvm::Expected<llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>>
|
|
SearchPathOptions::makeOverlayFileSystem(
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> BaseFS) const {
|
|
// TODO: This implementation is different to how Clang reads overlays in.
|
|
// Expose a helper in Clang rather than doing this ourselves.
|
|
|
|
auto OverlayFS =
|
|
llvm::makeIntrusiveRefCnt<llvm::vfs::OverlayFileSystem>(BaseFS);
|
|
|
|
llvm::Error AllErrors = llvm::Error::success();
|
|
bool hasOverlays = false;
|
|
for (const auto &File : VFSOverlayFiles) {
|
|
hasOverlays = true;
|
|
if (auto Err = loadAndValidateVFSOverlay(File, BaseFS, OverlayFS))
|
|
AllErrors = llvm::joinErrors(std::move(AllErrors), std::move(Err));
|
|
}
|
|
|
|
if (AllErrors)
|
|
return std::move(AllErrors);
|
|
|
|
if (hasOverlays)
|
|
return OverlayFS;
|
|
return BaseFS;
|
|
}
|