CMake: Fix "Jump to File" with special characters

Fixes "Jump to File" from the context menu and the ctrl+click navigation
for files that contain special characters.

Fixes: QTCREATORBUG-25572
Change-Id: I7c26c6d517ced26f803c2224f0c09397f373b3b5
Reviewed-by: Cristian Adam <cristian.adam@qt.io>
This commit is contained in:
Eike Ziller
2021-04-12 15:29:08 +02:00
parent e160c962ac
commit 82bb6a3c72

View File

@@ -119,11 +119,36 @@ void CMakeEditorWidget::contextMenuEvent(QContextMenuEvent *e)
showDefaultContextMenu(e, Constants::M_CONTEXT); showDefaultContextMenu(e, Constants::M_CONTEXT);
} }
static bool isValidFileNameChar(const QChar &c) static bool mustBeQuotedInFileName(const QChar &c)
{ {
return c.isLetterOrNumber() || c == QLatin1Char('.') || c == QLatin1Char('_') return c.isSpace() || c == '"' || c == '(' || c == ')';
|| c == QLatin1Char('-') || c == QLatin1Char('/') || c == QLatin1Char('\\') || c == '{' }
|| c == '}' || c == '$';
static bool isValidFileNameChar(const QString &block, int pos)
{
const QChar c = block.at(pos);
return !mustBeQuotedInFileName(c) || (pos > 0 && block.at(pos - 1) == '\\');
}
static QString unescape(const QString &s)
{
QString result;
int i = 0;
const int size = s.size();
while (i < size) {
const QChar c = s.at(i);
if (c == '\\' && i < size - 1) {
const QChar nc = s.at(i + 1);
if (mustBeQuotedInFileName(nc)) {
result += nc;
i += 2;
continue;
}
}
result += c;
++i;
}
return result;
} }
void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor, void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
@@ -149,9 +174,8 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
QString buffer; QString buffer;
int beginPos = positionInBlock - 1; int beginPos = positionInBlock - 1;
while (beginPos >= 0) { while (beginPos >= 0) {
QChar c = block.at(beginPos); if (isValidFileNameChar(block, beginPos)) {
if (isValidFileNameChar(c)) { buffer.prepend(block.at(beginPos));
buffer.prepend(c);
beginPos--; beginPos--;
} else { } else {
break; break;
@@ -161,9 +185,8 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
// find the end of a filename // find the end of a filename
int endPos = positionInBlock; int endPos = positionInBlock;
while (endPos < block.count()) { while (endPos < block.count()) {
QChar c = block.at(endPos); if (isValidFileNameChar(block, endPos)) {
if (isValidFileNameChar(c)) { buffer.append(block.at(endPos));
buffer.append(c);
endPos++; endPos++;
} else { } else {
break; break;
@@ -176,10 +199,9 @@ void CMakeEditorWidget::findLinkAt(const QTextCursor &cursor,
QDir dir(textDocument()->filePath().toFileInfo().absolutePath()); QDir dir(textDocument()->filePath().toFileInfo().absolutePath());
buffer.replace("${CMAKE_CURRENT_SOURCE_DIR}", dir.path()); buffer.replace("${CMAKE_CURRENT_SOURCE_DIR}", dir.path());
buffer.replace("${CMAKE_CURRENT_LIST_DIR}", dir.path()); buffer.replace("${CMAKE_CURRENT_LIST_DIR}", dir.path());
// TODO: Resolve more variables // TODO: Resolve more variables
QString fileName = dir.filePath(buffer); QString fileName = dir.filePath(unescape(buffer));
QFileInfo fi(fileName); QFileInfo fi(fileName);
if (fi.exists()) { if (fi.exists()) {
if (fi.isDir()) { if (fi.isDir()) {