diff --git a/ets2panda/util/arktsconfig.cpp b/ets2panda/util/arktsconfig.cpp index fc8c263731aa5de5991b7a9ef7ba4128ce78daeb..f95b1c3abd86d76bee4f646cc3dd5b65988289ba 100644 --- a/ets2panda/util/arktsconfig.cpp +++ b/ets2panda/util/arktsconfig.cpp @@ -115,9 +115,24 @@ std::string ArkTsConfig::Pattern::GetSearchRoot() const bool ArkTsConfig::Pattern::Match(const std::string &path) const { ASSERT(fs::path(path).is_absolute()); - fs::path value = fs::path(value_); + const fs::path value = fs::weakly_canonical(value_); std::string pattern = value.is_absolute() ? value.string() : (base_ / value).string(); +#ifdef PANDA_TARGET_WINDOWS + // Backslash escape except for regexp control sequences + pattern = std::regex_replace( + std::regex_replace(pattern, std::regex(R"(\\)"), R"(\\)"), + std::regex(R"(\\[\.])"), "."); + // Replace arktsconfig special symbols with regular expressions + if (IsPattern()) { + // '**' matches any directory nested to any level + pattern = std::regex_replace(pattern, std::regex(R"(\*\*\\\\)"), ".*"); + // '*' matches zero or more characters (excluding directory separators) + pattern = std::regex_replace(pattern, std::regex(R"(([^\.])\*)"), R"($1[^\\]*)"); + // '?' matches any one character (excluding directory separators) + pattern = std::regex_replace(pattern, std::regex(R"("\?")"), R"([^\\])"); + } +#else // Replace arktsconfig special symbols with regular expressions if (IsPattern()) { // '**' matches any directory nested to any level @@ -131,6 +146,7 @@ bool ArkTsConfig::Pattern::Match(const std::string &path) const // default extensions to match pattern += R"(.*(\.ts|\.d\.ts|\.sts)$)"; } +#endif // PANDA_TARGET_WINDOWS std::smatch m; auto res = std::regex_match(path, m, std::regex(pattern)); return res; @@ -459,7 +475,7 @@ static std::vector GetSourceList(const std::shared_ptr &a // Collect "include" // TSC traverses folders for sources starting from 'include' rather than from 'rootDir', so we do the same for (auto &include : includes) { - auto traverseRoot = fs::path(include.GetSearchRoot()); + auto traverseRoot = fs::weakly_canonical(include.GetSearchRoot()); if (!fs::exists(traverseRoot)) { continue; } @@ -471,7 +487,7 @@ static std::vector GetSourceList(const std::shared_ptr &a } for (const auto &dirEntry : fs::recursive_directory_iterator(traverseRoot)) { if (include.Match(dirEntry.path().string()) && !MatchExcludes(dirEntry, excludes)) { - sourceList.emplace_back(dirEntry); + sourceList.emplace_back(fs::weakly_canonical(dirEntry)); } } } @@ -484,7 +500,7 @@ static fs::path Relative(const fs::path &src, const fs::path &base) { fs::path tmpPath = src; fs::path relPath; - while (!fs::equivalent(tmpPath, base)) { + while (!fs::equivalent(fs::weakly_canonical(tmpPath), fs::weakly_canonical(base))) { relPath = relPath.empty() ? tmpPath.filename() : tmpPath.filename() / relPath; if (tmpPath == tmpPath.parent_path()) { return fs::path(); diff --git a/ets2panda/util/importPathManager.cpp b/ets2panda/util/importPathManager.cpp index 177a50d0186866583eb9cbcc4bcc239e4914aa30..3e41de7e2b4f4a45206a279bfedbb97967abecec 100644 --- a/ets2panda/util/importPathManager.cpp +++ b/ets2panda/util/importPathManager.cpp @@ -29,6 +29,13 @@ namespace fs = std::filesystem; namespace fs = std::experimental::filesystem; #endif #endif + +#ifdef PANDA_TARGET_WINDOWS +constexpr std::string_view importPathDelimiter = "/"; +#else +constexpr std::string_view importPathDelimiter = ark::os::file::File::GetPathDelim(); +#endif + namespace ark::es2panda::util { constexpr size_t SUPPORTED_INDEX_FILES_SIZE = 2; @@ -58,7 +65,7 @@ StringView ImportPathManager::ResolvePath(const StringView ¤tModulePath, c } std::string baseUrl; - if (importPath.Mutf8()[0] == pathDelimiter_.at(0)) { + if (importPath.Mutf8()[0] == importPathDelimiter.at(0)) { baseUrl = arktsConfig_->BaseUrl(); baseUrl.append(importPath.Mutf8(), 0, importPath.Mutf8().length()); return AppendExtensionOrIndexFileIfOmitted(UString(baseUrl, allocator_).View()); @@ -69,12 +76,12 @@ StringView ImportPathManager::ResolvePath(const StringView ¤tModulePath, c return AppendExtensionOrIndexFileIfOmitted(importPath); } - const size_t pos = importPath.Mutf8().find(pathDelimiter_); + const size_t pos = importPath.Mutf8().find(importPathDelimiter); bool containsDelim = (pos != std::string::npos); auto rootPart = containsDelim ? importPath.Substr(0, pos) : importPath; if (!stdLib_.empty() && (rootPart.Is("std") || rootPart.Is("escompat"))) { // Get std or escompat path from CLI if provided - baseUrl = stdLib_ + pathDelimiter_.at(0) + rootPart.Mutf8(); + baseUrl = stdLib_ + importPathDelimiter.at(0) + rootPart.Mutf8(); } else { ASSERT(arktsConfig_ != nullptr); auto resolvedPath = arktsConfig_->ResolvePath(importPath.Mutf8()); @@ -228,8 +235,8 @@ bool ImportPathManager::IsRelativePath(const StringView &path) const std::string currentDirReference = "."; std::string parentDirReference = ".."; - currentDirReference.append(pathDelimiter_); - parentDirReference.append(pathDelimiter_); + currentDirReference.append(importPathDelimiter); + parentDirReference.append(importPathDelimiter); return ((path.Mutf8().find(currentDirReference) == 0) || (path.Mutf8().find(parentDirReference) == 0)); }