Move filename line split into Utils::Link

Since we already have a container for file path, line and column move
the parse function there.

Change-Id: I5d0d97d271c5aaeb618e1a303b02cc6514e94e81
Reviewed-by: hjk <hjk@qt.io>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
David Schulz
2021-05-25 11:10:31 +02:00
parent 356bfcc9fd
commit fc53dc27e4
13 changed files with 192 additions and 153 deletions

View File

@@ -78,7 +78,7 @@ add_qtc_library(Utils
jsontreeitem.cpp jsontreeitem.h
layoutbuilder.cpp layoutbuilder.h
linecolumn.h
link.h
link.cpp link.h
listmodel.h
listutils.h
macroexpander.cpp macroexpander.h

74
src/libs/utils/link.cpp Normal file
View File

@@ -0,0 +1,74 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "link.h"
#include <QRegularExpression>
namespace Utils {
/*!
Returns the Link to \a fileName.
If \a canContainLineNumber is true the line number, and column number components
are extracted from \a fileName and the found \a postFix is set.
The following patterns are supported: \c {filepath.txt:19},
\c{filepath.txt:19:12}, \c {filepath.txt+19},
\c {filepath.txt+19+12}, and \c {filepath.txt(19)}.
*/
Link Link::fromString(const QString &fileName, bool canContainLineNumber, QString *postfix)
{
if (!canContainLineNumber)
return {Utils::FilePath::fromString(fileName)};
// :10:2 GCC/Clang-style
static const auto regexp = QRegularExpression("[:+](\\d+)?([:+](\\d+)?)?$");
// (10) MSVC-style
static const auto vsRegexp = QRegularExpression("[(]((\\d+)[)]?)?$");
const QRegularExpressionMatch match = regexp.match(fileName);
QString filePath = fileName;
int line = -1;
int column = -1;
if (match.hasMatch()) {
if (postfix)
*postfix = match.captured(0);
filePath = fileName.left(match.capturedStart(0));
line = 0; // for the case that there's only a : at the end
if (match.lastCapturedIndex() > 0) {
line = match.captured(1).toInt();
if (match.lastCapturedIndex() > 2) // index 2 includes the + or : for the column number
column = match.captured(3).toInt() - 1; //column is 0 based, despite line being 1 based
}
} else {
const QRegularExpressionMatch vsMatch = vsRegexp.match(fileName);
if (postfix)
*postfix = vsMatch.captured(0);
filePath = fileName.left(vsMatch.capturedStart(0));
if (vsMatch.lastCapturedIndex() > 1) // index 1 includes closing )
line = vsMatch.captured(2).toInt();
}
return {Utils::FilePath::fromString(filePath), line, column};
}
} // namespace Utils

View File

@@ -35,7 +35,7 @@
namespace Utils {
struct Link
struct QTCREATOR_UTILS_EXPORT Link
{
Link(const Utils::FilePath &filePath = Utils::FilePath(), int line = 0, int column = 0)
: targetFilePath(filePath)
@@ -43,6 +43,10 @@ struct Link
, targetColumn(column)
{}
static Link fromString(const QString &fileName,
bool canContainLineNumber = false,
QString *postfix = nullptr);
bool hasValidTarget() const
{ return !targetFilePath.isEmpty(); }

View File

@@ -142,7 +142,8 @@ SOURCES += \
$$PWD/layoutbuilder.cpp \
$$PWD/variablechooser.cpp \
$$PWD/futuresynchronizer.cpp \
$$PWD/qtcsettings.cpp
$$PWD/qtcsettings.cpp \
$$PWD/link.cpp \
HEADERS += \
$$PWD/environmentfwd.h \

View File

@@ -162,6 +162,7 @@ Project {
"layoutbuilder.cpp",
"layoutbuilder.h",
"linecolumn.h",
"link.cpp",
"link.h",
"listmodel.h",
"listutils.h",

View File

@@ -77,8 +77,6 @@ public slots:
private slots:
void testVcsManager_data();
void testVcsManager();
void testSplitLineAndColumnNumber();
void testSplitLineAndColumnNumber_data();
// Locator:
void test_basefilefilter();
void test_basefilefilter_data();

View File

@@ -68,6 +68,7 @@
#include <utils/fileutils.h>
#include <utils/hostosinfo.h>
#include <utils/infobar.h>
#include <utils/link.h>
#include <utils/macroexpander.h>
#include <utils/mimetypes/mimedatabase.h>
#include <utils/mimetypes/mimetype.h>
@@ -793,10 +794,10 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const FilePath &file
int lineNumber = -1;
int columnNumber = -1;
if ((flags & EditorManager::CanContainLineAndColumnNumber) && !fi.exists()) {
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(fn);
fn = Utils::FileUtils::normalizePathName(fp.filePath);
lineNumber = fp.lineNumber;
columnNumber = fp.columnNumber;
Link link = Link::fromString(fn, true);
fn = Utils::FileUtils::normalizePathName(link.targetFilePath.toString());
lineNumber = link.targetLine;
columnNumber = link.targetColumn;
} else {
fn = Utils::FileUtils::normalizePathName(fn);
}
@@ -3156,44 +3157,6 @@ void EditorManager::openEditorAtSearchResult(const SearchResultItem &item,
newEditor);
}
/*!
Returns the file path \a fullFilePath split into its file path, line
number, and column number components.
The following patterns are supported: \c {filepath.txt:19},
\c{filepath.txt:19:12}, \c {filepath.txt+19},
\c {filepath.txt+19+12}, and \c {filepath.txt(19)}.
*/
EditorManager::FilePathInfo EditorManager::splitLineAndColumnNumber(const QString &fullFilePath)
{
// :10:2 GCC/Clang-style
static const auto regexp = QRegularExpression("[:+](\\d+)?([:+](\\d+)?)?$");
// (10) MSVC-style
static const auto vsRegexp = QRegularExpression("[(]((\\d+)[)]?)?$");
const QRegularExpressionMatch match = regexp.match(fullFilePath);
QString postfix;
QString filePath = fullFilePath;
int line = -1;
int column = -1;
if (match.hasMatch()) {
postfix = match.captured(0);
filePath = fullFilePath.left(match.capturedStart(0));
line = 0; // for the case that there's only a : at the end
if (match.lastCapturedIndex() > 0) {
line = match.captured(1).toInt();
if (match.lastCapturedIndex() > 2) // index 2 includes the + or : for the column number
column = match.captured(3).toInt() - 1; //column is 0 based, despite line being 1 based
}
} else {
const QRegularExpressionMatch vsMatch = vsRegexp.match(fullFilePath);
postfix = vsMatch.captured(0);
filePath = fullFilePath.left(vsMatch.capturedStart(0));
if (vsMatch.lastCapturedIndex() > 1) // index 1 includes closing )
line = vsMatch.captured(2).toInt();
}
return {filePath, postfix, line, column};
}
/*!
Returns whether \a fileName is an auto-save file created by \QC.
*/
@@ -3815,79 +3778,3 @@ void EditorManager::setWindowTitleVcsTopicHandler(WindowTitleHandler handler)
{
d->m_titleVcsTopicHandler = handler;
}
#if defined(WITH_TESTS)
void CorePlugin::testSplitLineAndColumnNumber()
{
QFETCH(QString, testFile);
QFETCH(QString, filePath);
QFETCH(QString, postfix);
QFETCH(int, line);
QFETCH(int, column);
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(testFile);
QCOMPARE(fp.filePath, filePath);
QCOMPARE(fp.postfix, postfix);
QCOMPARE(fp.lineNumber, line);
QCOMPARE(fp.columnNumber, column);
}
void CorePlugin::testSplitLineAndColumnNumber_data()
{
QTest::addColumn<QString>("testFile");
QTest::addColumn<QString>("filePath");
QTest::addColumn<QString>("postfix");
QTest::addColumn<int>("line");
QTest::addColumn<int>("column");
QTest::newRow("no-line-no-column") << QString::fromLatin1("someFile.txt")
<< QString::fromLatin1("someFile.txt")
<< QString() << -1 << -1;
QTest::newRow(": at end") << QString::fromLatin1("someFile.txt:")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1(":") << 0 << -1;
QTest::newRow("+ at end") << QString::fromLatin1("someFile.txt+")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1("+") << 0 << -1;
QTest::newRow(": for column") << QString::fromLatin1("someFile.txt:10:")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1(":10:") << 10 << -1;
QTest::newRow("+ for column") << QString::fromLatin1("someFile.txt:10+")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1(":10+") << 10 << -1;
QTest::newRow(": and + at end") << QString::fromLatin1("someFile.txt:+")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1(":+") << 0 << -1;
QTest::newRow("empty line") << QString::fromLatin1("someFile.txt:+10")
<< QString::fromLatin1("someFile.txt")
<< QString::fromLatin1(":+10") << 0 << 9;
QTest::newRow(":line-no-column") << QString::fromLatin1("/some/path/file.txt:42")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1(":42") << 42 << -1;
QTest::newRow("+line-no-column") << QString::fromLatin1("/some/path/file.txt+42")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("+42") << 42 << -1;
QTest::newRow(":line-:column") << QString::fromLatin1("/some/path/file.txt:42:3")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1(":42:3") << 42 << 2;
QTest::newRow(":line-+column") << QString::fromLatin1("/some/path/file.txt:42+33")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1(":42+33") << 42 << 32;
QTest::newRow("+line-:column") << QString::fromLatin1("/some/path/file.txt+142:30")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("+142:30") << 142 << 29;
QTest::newRow("+line-+column") << QString::fromLatin1("/some/path/file.txt+142+33")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("+142+33") << 142 << 32;
QTest::newRow("( at end") << QString::fromLatin1("/some/path/file.txt(")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("(") << -1 << -1;
QTest::newRow("(42 at end") << QString::fromLatin1("/some/path/file.txt(42")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("(42") << 42 << -1;
QTest::newRow("(42) at end") << QString::fromLatin1("/some/path/file.txt(42)")
<< QString::fromLatin1("/some/path/file.txt")
<< QString::fromLatin1("(42)") << 42 << -1;
}
#endif // WITH_TESTS

View File

@@ -86,14 +86,6 @@ public:
};
Q_DECLARE_FLAGS(OpenEditorFlags, OpenEditorFlag)
struct FilePathInfo {
QString filePath; // file path without line/column suffix
QString postfix; // line/column suffix as string, e.g. ":10:1"
int lineNumber; // extracted line number, -1 if none
int columnNumber; // extracted column number, -1 if none
};
static FilePathInfo splitLineAndColumnNumber(const QString &filePath);
static IEditor *openEditor(const Utils::FilePath &filePath, Utils::Id editorId = {},
OpenEditorFlags flags = NoFlags, bool *newEditor = nullptr);
static IEditor *openEditorAt(const Utils::FilePath &filePath, int line, int column = 0,

View File

@@ -28,6 +28,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <utils/algorithm.h>
#include <utils/fileutils.h>
#include <utils/link.h>
#include <utils/qtcassert.h>
#include <QDir>
@@ -137,9 +138,10 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QList<LocatorFilterEntry> entries[int(MatchLevel::Count)];
// If search string contains spaces, treat them as wildcard '*' and search in full path
const QString entry = QDir::fromNativeSeparators(origEntry).replace(' ', '*');
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
QString postfix;
Link link = Link::fromString(entry, true, &postfix);
const QRegularExpression regexp = createRegExp(fp.filePath);
const QRegularExpression regexp = createRegExp(link.targetFilePath.toString());
if (!regexp.isValid()) {
d->m_current.clear(); // free memory
return {};
@@ -148,9 +150,9 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
return candidate.contains('/') || candidate.contains('*');
};
const bool hasPathSeparator = containsPathSeparator(fp.filePath);
const bool hasPathSeparator = containsPathSeparator(link.targetFilePath.toString());
const bool containsPreviousEntry = !d->m_current.previousEntry.isEmpty()
&& fp.filePath.contains(d->m_current.previousEntry);
&& link.targetFilePath.toString().contains(d->m_current.previousEntry);
const bool pathSeparatorAdded = !containsPathSeparator(d->m_current.previousEntry)
&& hasPathSeparator;
const bool searchInPreviousResults = !d->m_current.forceNewSearchList && containsPreviousEntry
@@ -160,7 +162,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
QTC_ASSERT(d->m_current.iterator.data(), return QList<LocatorFilterEntry>());
d->m_current.previousResultPaths.clear();
d->m_current.previousEntry = fp.filePath;
d->m_current.previousEntry = link.targetFilePath.toString();
d->m_current.iterator->toFront();
bool canceled = false;
while (d->m_current.iterator->hasNext()) {
@@ -176,7 +178,7 @@ QList<LocatorFilterEntry> BaseFileFilter::matchesFor(QFutureInterface<LocatorFil
if (match.hasMatch()) {
QFileInfo fi(path.toString());
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path.toString() + fp.postfix));
LocatorFilterEntry filterEntry(this, fi.fileName(), QString(path.toString() + postfix));
filterEntry.fileName = path.toString();
filterEntry.extraInfo = FilePath::fromFileInfo(fi).shortNativePath();

View File

@@ -36,6 +36,7 @@
#include <coreplugin/vcsmanager.h>
#include <utils/checkablemessagebox.h>
#include <utils/fileutils.h>
#include <utils/link.h>
#include <QDir>
#include <QJsonObject>
@@ -128,11 +129,11 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
}
}
// file names can match with +linenumber or :linenumber
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entryFileName);
regExp = createRegExp(fp.filePath, caseSensitivity_);
QString postfix;
Link link = Link::fromString(entry, true, &postfix);
regExp = createRegExp(link.targetFilePath.toString(), caseSensitivity_);
if (!regExp.isValid())
return {};
const QString fileName = QFileInfo(fp.filePath).fileName();
for (const QString &file : files) {
if (future.isCanceled())
break;
@@ -141,7 +142,7 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
if (match.hasMatch()) {
const MatchLevel level = matchLevelFor(match, file);
const QString fullPath = dirInfo.filePath(file);
LocatorFilterEntry filterEntry(this, file, QString(fullPath + fp.postfix));
LocatorFilterEntry filterEntry(this, file, QString(fullPath + postfix));
filterEntry.fileName = fullPath;
filterEntry.highlightInfo = highlightInfo(match);
@@ -150,7 +151,7 @@ QList<LocatorFilterEntry> FileSystemFilter::matchesFor(QFutureInterface<LocatorF
}
// "create and open" functionality
const QString fullFilePath = dirInfo.filePath(fileName);
const QString fullFilePath = dirInfo.filePath(link.targetFilePath.fileName());
const bool containsWildcard = entry.contains('?') || entry.contains('*');
if (!containsWildcard && !QFileInfo::exists(fullFilePath) && dirInfo.exists()) {
LocatorFilterEntry createAndOpen(this, tr("Create and Open \"%1\"").arg(entry), fullFilePath);

View File

@@ -28,6 +28,7 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <utils/fileutils.h>
#include <utils/link.h>
#include <QAbstractItemModel>
#include <QFileInfo>
@@ -59,9 +60,10 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
{
QList<LocatorFilterEntry> goodEntries;
QList<LocatorFilterEntry> betterEntries;
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
QString postfix;
Link link = Link::fromString(entry, true, &postfix);
const QRegularExpression regexp = createRegExp(fp.filePath);
const QRegularExpression regexp = createRegExp(link.targetFilePath.toString());
if (!regexp.isValid())
return goodEntries;
@@ -75,7 +77,7 @@ QList<LocatorFilterEntry> OpenDocumentsFilter::matchesFor(QFutureInterface<Locat
QString displayName = editorEntry.displayName;
const QRegularExpressionMatch match = regexp.match(displayName);
if (match.hasMatch()) {
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + fp.postfix));
LocatorFilterEntry filterEntry(this, displayName, QString(fileName + postfix));
filterEntry.extraInfo = FilePath::fromString(fileName).shortNativePath();
filterEntry.fileName = fileName;
filterEntry.highlightInfo = highlightInfo(match);

View File

@@ -30,11 +30,12 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/reaper.h>
#include <utils/algorithm.h>
#include <utils/commandline.h>
#include <utils/environment.h>
#include <utils/fancylineedit.h>
#include <utils/link.h>
#include <utils/macroexpander.h>
#include <utils/pathchooser.h>
#include <utils/commandline.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/variablechooser.h>
@@ -251,17 +252,17 @@ SpotlightLocatorFilter::SpotlightLocatorFilter()
void SpotlightLocatorFilter::prepareSearch(const QString &entry)
{
const EditorManager::FilePathInfo fp = EditorManager::splitLineAndColumnNumber(entry);
if (fp.filePath.isEmpty()) {
Link link = Utils::Link::fromString(entry, true);
if (link.targetFilePath.isEmpty()) {
setFileIterator(new BaseFileFilter::ListIterator(Utils::FilePaths()));
} else {
// only pass the file name part to allow searches like "somepath/*foo"
int lastSlash = fp.filePath.lastIndexOf(QLatin1Char('/'));
const QString query = fp.filePath.mid(lastSlash + 1);
std::unique_ptr<MacroExpander> expander(createMacroExpander(query));
std::unique_ptr<MacroExpander> expander(createMacroExpander(link.targetFilePath.fileName()));
const QString argumentString = expander->expand(
caseSensitivity(fp.filePath) == Qt::CaseInsensitive ? m_arguments
: m_caseSensitiveArguments);
caseSensitivity(link.targetFilePath.toString()) == Qt::CaseInsensitive
? m_arguments
: m_caseSensitiveArguments);
setFileIterator(
new SpotlightIterator(QStringList(m_command) + ProcessArgs::splitArgs(argumentString)));
}

View File

@@ -27,6 +27,7 @@
#include <QDebug>
#include <utils/fileutils.h>
#include <utils/link.h>
//TESTED_COMPONENT=src/libs/utils
using namespace Utils;
@@ -54,6 +55,8 @@ private slots:
void fromToString();
void comparison_data();
void comparison();
void linkFromString_data();
void linkFromString();
private:
QTemporaryDir tempDir;
@@ -364,5 +367,78 @@ void tst_fileutils::comparison_data()
QTest::newRow("s4") << "x://y/abc" << "x://y/abc" << false << true;
}
void tst_fileutils::linkFromString()
{
QFETCH(QString, testFile);
QFETCH(Utils::FilePath, filePath);
QFETCH(QString, postfix);
QFETCH(int, line);
QFETCH(int, column);
QString extractedPostfix;
Link link = Link::fromString(testFile, true, &extractedPostfix);
QCOMPARE(link.targetFilePath, filePath);
QCOMPARE(extractedPostfix, postfix);
QCOMPARE(link.targetLine, line);
QCOMPARE(link.targetColumn, column);
}
void tst_fileutils::linkFromString_data()
{
QTest::addColumn<QString>("testFile");
QTest::addColumn<Utils::FilePath>("filePath");
QTest::addColumn<QString>("postfix");
QTest::addColumn<int>("line");
QTest::addColumn<int>("column");
QTest::newRow("no-line-no-column")
<< QString::fromLatin1("someFile.txt") << Utils::FilePath::fromString("someFile.txt")
<< QString() << -1 << -1;
QTest::newRow(": at end") << QString::fromLatin1("someFile.txt:")
<< Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1(":") << 0 << -1;
QTest::newRow("+ at end") << QString::fromLatin1("someFile.txt+")
<< Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1("+") << 0 << -1;
QTest::newRow(": for column") << QString::fromLatin1("someFile.txt:10:")
<< Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1(":10:") << 10 << -1;
QTest::newRow("+ for column") << QString::fromLatin1("someFile.txt:10+")
<< Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1(":10+") << 10 << -1;
QTest::newRow(": and + at end")
<< QString::fromLatin1("someFile.txt:+") << Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1(":+") << 0 << -1;
QTest::newRow("empty line") << QString::fromLatin1("someFile.txt:+10")
<< Utils::FilePath::fromString("someFile.txt")
<< QString::fromLatin1(":+10") << 0 << 9;
QTest::newRow(":line-no-column") << QString::fromLatin1("/some/path/file.txt:42")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1(":42") << 42 << -1;
QTest::newRow("+line-no-column") << QString::fromLatin1("/some/path/file.txt+42")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("+42") << 42 << -1;
QTest::newRow(":line-:column") << QString::fromLatin1("/some/path/file.txt:42:3")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1(":42:3") << 42 << 2;
QTest::newRow(":line-+column") << QString::fromLatin1("/some/path/file.txt:42+33")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1(":42+33") << 42 << 32;
QTest::newRow("+line-:column") << QString::fromLatin1("/some/path/file.txt+142:30")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("+142:30") << 142 << 29;
QTest::newRow("+line-+column") << QString::fromLatin1("/some/path/file.txt+142+33")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("+142+33") << 142 << 32;
QTest::newRow("( at end") << QString::fromLatin1("/some/path/file.txt(")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("(") << -1 << -1;
QTest::newRow("(42 at end") << QString::fromLatin1("/some/path/file.txt(42")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("(42") << 42 << -1;
QTest::newRow("(42) at end") << QString::fromLatin1("/some/path/file.txt(42)")
<< Utils::FilePath::fromString("/some/path/file.txt")
<< QString::fromLatin1("(42)") << 42 << -1;
}
QTEST_APPLESS_MAIN(tst_fileutils)
#include "tst_fileutils.moc"