diff --git a/src/libs/languageserverprotocol/lsptypes.cpp b/src/libs/languageserverprotocol/lsptypes.cpp index b15e59f9bdd..4faf420e3a0 100644 --- a/src/libs/languageserverprotocol/lsptypes.cpp +++ b/src/libs/languageserverprotocol/lsptypes.cpp @@ -326,19 +326,26 @@ bool Range::overlaps(const Range &range) const return end() > range.start() && start() < range.end(); } +QString expressionForGlob(QString globPattern) +{ + const QString anySubDir("qtc_anysubdir_id"); + globPattern.replace("**/", anySubDir); + QString regexp = QRegularExpression::wildcardToRegularExpression(globPattern); + regexp.replace(anySubDir,"(.*[/\\\\])*"); + regexp.replace("\\{", "("); + regexp.replace("\\}", ")"); + regexp.replace(",", "|"); + return regexp; +} + bool DocumentFilter::applies(const Utils::FilePath &fileName, const Utils::MimeType &mimeType) const { - if (Utils::optional _scheme = scheme()) { - if (_scheme.value() == fileName.toString()) - return true; - } if (Utils::optional _pattern = pattern()) { QRegularExpression::PatternOption option = QRegularExpression::NoPatternOption; - if (Utils::HostOsInfo::fileNameCaseSensitivity() == Qt::CaseInsensitive) + if (fileName.caseSensitivity() == Qt::CaseInsensitive) option = QRegularExpression::CaseInsensitiveOption; - QRegularExpression regexp(QRegularExpression::wildcardToRegularExpression(_pattern.value()), - option); - if (regexp.match(fileName.toString()).hasMatch()) + const QRegularExpression regexp(expressionForGlob(_pattern.value()), option); + if (regexp.isValid() && regexp.match(fileName.toString()).hasMatch()) return true; } if (Utils::optional _lang = language()) { diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h index 1c6820a4aa9..bcf8e47d89c 100644 --- a/src/libs/languageserverprotocol/lsptypes.h +++ b/src/libs/languageserverprotocol/lsptypes.h @@ -377,7 +377,21 @@ public: void setScheme(const QString &scheme) { insert(schemeKey, scheme); } void clearScheme() { remove(schemeKey); } - // A glob pattern, like `*.{ts,js}`. + /** + * A glob pattern, like `*.{ts,js}`. + * + * Glob patterns can have the following syntax: + * - `*` to match one or more characters in a path segment + * - `?` to match on one character in a path segment + * - `**` to match any number of path segments, including none + * - `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` + * matches all TypeScript and JavaScript files) + * - `[]` to declare a range of characters to match in a path segment + * (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …) + * - `[!...]` to negate a range of characters to match in a path segment + * (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but + * not `example.0`) + */ Utils::optional pattern() const { return optionalValue(patternKey); } void setPattern(const QString &pattern) { insert(patternKey, pattern); } void clearPattern() { remove(patternKey); }