From 9289ec491b5c06e7fabac4a97bca12e3a6131c84 Mon Sep 17 00:00:00 2001 From: David Schulz Date: Tue, 15 Jun 2021 11:14:27 +0200 Subject: [PATCH] LSP: fix DocumentFilter glob matcher The following pattern were not interpreted by QRegularExpression::wildcardToRegularExpression. * - `**` to match any number of path segments, including none * - `{}` to group sub patterns into an OR expression. Task-number: QTCREATORBUG-25766 Change-Id: If7cafef4bf625690fc7dff8ac6461351fef79505 Reviewed-by: Christian Stenger --- src/libs/languageserverprotocol/lsptypes.cpp | 23 +++++++++++++------- src/libs/languageserverprotocol/lsptypes.h | 16 +++++++++++++- 2 files changed, 30 insertions(+), 9 deletions(-) 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); }