summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarco Bubke <marco.bubke@theqtcompany.com>2015-04-15 18:02:37 +0200
committerMarco Bubke <marco.bubke@theqtcompany.com>2015-04-20 11:32:29 +0000
commitf49cf4892e47b50adf40826e6f4fb9ece77b4c74 (patch)
tree50768836969e27fe304a4638577e32c6905127d5
parent75be3e0f54fac9790fc8e2974735e9208dc9e007 (diff)
downloadqt-creator-f49cf4892e47b50adf40826e6f4fb9ece77b4c74.tar.gz
Add unsaved files
Change-Id: I18125404b37ce4ebc35d0e94ee491da50c10b9cf Reviewed-by: Marco Bubke <marco.bubke@theqtcompany.com>
-rw-r--r--src/libs/sqlite/source/utf8string.cpp4
-rw-r--r--src/libs/sqlite/source/utf8string.h2
-rw-r--r--src/tools/codemodelbackend/ipcsource/codemodelbackendclangipc-source.pri6
-rw-r--r--src/tools/codemodelbackend/ipcsource/unsavedfiles.cpp118
-rw-r--r--src/tools/codemodelbackend/ipcsource/unsavedfiles.h67
-rw-r--r--tests/unit/codemodelbackend/unittest/unittest.pro3
-rw-r--r--tests/unit/codemodelbackend/unittest/unsavedfilestest.cpp132
-rw-r--r--tests/unit/codemodelbackend/unittest/utf8test.cpp8
8 files changed, 337 insertions, 3 deletions
diff --git a/src/libs/sqlite/source/utf8string.cpp b/src/libs/sqlite/source/utf8string.cpp
index bb6b745f89..4ff55a66bd 100644
--- a/src/libs/sqlite/source/utf8string.cpp
+++ b/src/libs/sqlite/source/utf8string.cpp
@@ -198,6 +198,10 @@ bool operator ==(const Utf8String &first, const Utf8String &second)
return first.byteArray == second.byteArray;
}
+bool operator ==(const Utf8String &first, const char *second)
+{
+ return first.byteArray == second;
+}
bool operator <(const Utf8String &first, const Utf8String &second)
{
diff --git a/src/libs/sqlite/source/utf8string.h b/src/libs/sqlite/source/utf8string.h
index bcb33c1be1..960f007148 100644
--- a/src/libs/sqlite/source/utf8string.h
+++ b/src/libs/sqlite/source/utf8string.h
@@ -47,6 +47,7 @@ class SQLITE_EXPORT Utf8String
friend SQLITE_EXPORT bool operator !=(const Utf8String &first, const Utf8String &second);
friend SQLITE_EXPORT bool operator ==(const Utf8String &first, const Utf8String &second);
+ friend SQLITE_EXPORT bool operator ==(const Utf8String &first, const char *second);
friend SQLITE_EXPORT bool operator <(const Utf8String &first, const Utf8String &second);
friend SQLITE_EXPORT QDataStream &operator<<(QDataStream &datastream, const Utf8String &text);
@@ -103,6 +104,7 @@ SQLITE_EXPORT const Utf8String operator +(const Utf8String &first, const Utf8Str
SQLITE_EXPORT bool operator !=(const Utf8String &first, const Utf8String &second);
SQLITE_EXPORT bool operator ==(const Utf8String &first, const Utf8String &second);
+SQLITE_EXPORT bool operator ==(const Utf8String &first, const char *second);
SQLITE_EXPORT bool operator <(const Utf8String &first, const Utf8String &second);
SQLITE_EXPORT QDataStream &operator<<(QDataStream &datastream, const Utf8String &text);
diff --git a/src/tools/codemodelbackend/ipcsource/codemodelbackendclangipc-source.pri b/src/tools/codemodelbackend/ipcsource/codemodelbackendclangipc-source.pri
index 2df7cbad5f..f3193e08e1 100644
--- a/src/tools/codemodelbackend/ipcsource/codemodelbackendclangipc-source.pri
+++ b/src/tools/codemodelbackend/ipcsource/codemodelbackendclangipc-source.pri
@@ -9,7 +9,8 @@ HEADERS += clangipcserver.h \
$$PWD/translationunitfilenotexits.h \
$$PWD/codecompletefailedexception.h \
$$PWD/clangcodecompleteresults.h \
- $$PWD/codecompletionsextractor.h
+ $$PWD/codecompletionsextractor.h \
+ $$PWD/unsavedfiles.h
SOURCES += clangipcserver.cpp \
codecompleter.cpp \
@@ -19,4 +20,5 @@ SOURCES += clangipcserver.cpp \
$$PWD/translationunitfilenotexits.cpp \
$$PWD/codecompletefailedexception.cpp \
$$PWD/clangcodecompleteresults.cpp \
- $$PWD/codecompletionsextractor.cpp
+ $$PWD/codecompletionsextractor.cpp \
+ $$PWD/unsavedfiles.cpp
diff --git a/src/tools/codemodelbackend/ipcsource/unsavedfiles.cpp b/src/tools/codemodelbackend/ipcsource/unsavedfiles.cpp
new file mode 100644
index 0000000000..f6c66f00d2
--- /dev/null
+++ b/src/tools/codemodelbackend/ipcsource/unsavedfiles.cpp
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "unsavedfiles.h"
+
+
+#include <cstring>
+
+namespace CodeModelBackEnd {
+
+void UnsavedFiles::update(const QVector<FileContainer> &fileContainers)
+{
+ for (const FileContainer &fileContainer : fileContainers)
+ updateCXUnsavedFileWithFileContainer(fileContainer);
+}
+
+void UnsavedFiles::clear()
+{
+ for (const CXUnsavedFile &cxUnsavedFile : cxUnsavedFiles_)
+ deleteCXUnsavedFile(cxUnsavedFile);
+
+ cxUnsavedFiles_.clear();
+}
+
+int UnsavedFiles::unsavedFilesCount() const
+{
+ return cxUnsavedFiles_.size();
+}
+
+CXUnsavedFile *UnsavedFiles::cxUnsavedFiles() const
+{
+ return cxUnsavedFiles_.data();
+}
+
+const std::vector<CXUnsavedFile> &UnsavedFiles::cxUnsavedFileVector() const
+{
+ return cxUnsavedFiles_;
+}
+
+const CXUnsavedFile UnsavedFiles::createCxUnsavedFile(const Utf8String &filePath, const Utf8String &fileContent)
+{
+ char *cxUnsavedFilePath = new char[filePath.byteSize() + 1];
+ char *cxUnsavedFileContent = new char[fileContent.byteSize() + 1];
+
+ std::memcpy(cxUnsavedFilePath, filePath.constData(), filePath.byteSize() + 1);
+ std::memcpy(cxUnsavedFileContent, fileContent.constData(), fileContent.byteSize() + 1);
+
+ return CXUnsavedFile { cxUnsavedFilePath, cxUnsavedFileContent, ulong(fileContent.byteSize())};
+}
+
+void UnsavedFiles::deleteCXUnsavedFile(const CXUnsavedFile &cxUnsavedFile)
+{
+ delete [] cxUnsavedFile.Contents;
+ delete [] cxUnsavedFile.Filename;
+}
+
+void UnsavedFiles::updateCXUnsavedFileWithFileContainer(const FileContainer &fileContainer)
+{
+ if (fileContainer.hasUnsavedFileContent()) {
+ addOrUpdateCXUnsavedFile(fileContainer);
+ } else {
+ removeCXUnsavedFile(fileContainer);
+ }
+}
+
+void UnsavedFiles::removeCXUnsavedFile(const FileContainer &fileContainer)
+{
+ const Utf8String filePath = fileContainer.filePath();
+ auto isSameFile = [filePath] (const CXUnsavedFile &cxUnsavedFile) { return filePath == cxUnsavedFile.Filename; };
+
+ cxUnsavedFiles_.erase(std::remove_if(cxUnsavedFiles_.begin(), cxUnsavedFiles_.end(), isSameFile), cxUnsavedFiles_.end());
+}
+
+void UnsavedFiles::addOrUpdateCXUnsavedFile(const FileContainer &fileContainer)
+{
+ const Utf8String filePath = fileContainer.filePath();
+ const Utf8String fileContent = fileContainer.unsavedFileContent();
+ auto isSameFile = [filePath] (const CXUnsavedFile &cxUnsavedFile) { return filePath == cxUnsavedFile.Filename; };
+
+ auto cxUnsavedFileIterator = std::find_if(cxUnsavedFiles_.begin(), cxUnsavedFiles_.end(), isSameFile);
+ if (cxUnsavedFileIterator == cxUnsavedFiles_.end())
+ cxUnsavedFiles_.push_back(createCxUnsavedFile(filePath, fileContent));
+ else {
+ deleteCXUnsavedFile(*cxUnsavedFileIterator);
+ *cxUnsavedFileIterator = createCxUnsavedFile(filePath, fileContent);
+ }
+}
+
+
+} // namespace CodeModelBackEnd
+
diff --git a/src/tools/codemodelbackend/ipcsource/unsavedfiles.h b/src/tools/codemodelbackend/ipcsource/unsavedfiles.h
new file mode 100644
index 0000000000..ff49d24667
--- /dev/null
+++ b/src/tools/codemodelbackend/ipcsource/unsavedfiles.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#ifndef CODEMODELBACKEND_UNSAVEDFILES_H
+#define CODEMODELBACKEND_UNSAVEDFILES_H
+
+#include <filecontainer.h>
+
+#include <vector>
+#include <QVector>
+
+#include <clang-c/Index.h>
+
+namespace CodeModelBackEnd {
+
+class UnsavedFiles
+{
+public:
+ void update(const QVector<FileContainer> &fileContainers);
+ void clear();
+
+ int unsavedFilesCount() const;
+
+ CXUnsavedFile *cxUnsavedFiles() const;
+ const std::vector<CXUnsavedFile> &cxUnsavedFileVector() const;
+
+private:
+ const CXUnsavedFile createCxUnsavedFile(const Utf8String &filePath, const Utf8String &fileContent);
+ void deleteCXUnsavedFile(const CXUnsavedFile &cxUnsavedFile);
+ void updateCXUnsavedFileWithFileContainer(const FileContainer &fileContainer);
+ void removeCXUnsavedFile(const FileContainer &fileContainer);
+ void addOrUpdateCXUnsavedFile(const FileContainer &fileContainer);
+
+private:
+ mutable std::vector<CXUnsavedFile> cxUnsavedFiles_;
+};
+
+} // namespace CodeModelBackEnd
+
+#endif // CODEMODELBACKEND_UNSAVEDFILES_H
diff --git a/tests/unit/codemodelbackend/unittest/unittest.pro b/tests/unit/codemodelbackend/unittest/unittest.pro
index 3f5e085bb0..b7eb5f9981 100644
--- a/tests/unit/codemodelbackend/unittest/unittest.pro
+++ b/tests/unit/codemodelbackend/unittest/unittest.pro
@@ -53,7 +53,8 @@ SOURCES += main.cpp \
clangstringtest.cpp \
translationunittest.cpp \
clangcodecompleteresultstest.cpp \
- codecompletionsextractortest.cpp
+ codecompletionsextractortest.cpp \
+ unsavedfilestest.cpp
HEADERS += \
gtest-qt-printing.h \
diff --git a/tests/unit/codemodelbackend/unittest/unsavedfilestest.cpp b/tests/unit/codemodelbackend/unittest/unsavedfilestest.cpp
new file mode 100644
index 0000000000..eb5c5f3d36
--- /dev/null
+++ b/tests/unit/codemodelbackend/unittest/unsavedfilestest.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://www.qt.io/licensing. For further information
+** use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+****************************************************************************/
+
+#include "gtest/gtest.h"
+#include "gmock/gmock-matchers.h"
+#include "gmock/gmock.h"
+
+#include <unsavedfiles.h>
+#include <filecontainer.h>
+
+#include <QVector>
+
+using CodeModelBackEnd::UnsavedFiles;
+using CodeModelBackEnd::FileContainer;
+
+using ::testing::IsNull;
+using ::testing::NotNull;
+
+namespace {
+
+bool operator ==(const CodeModelBackEnd::FileContainer &fileContainer, const CXUnsavedFile &cxUnsavedFile)
+{
+ return fileContainer.filePath() == Utf8String::fromUtf8(cxUnsavedFile.Filename)
+ && fileContainer.unsavedFileContent() == Utf8String(cxUnsavedFile.Contents, cxUnsavedFile.Length);
+}
+
+bool fileContainersContainsCxUnsavedFile(const QVector<FileContainer> &fileContainers, const CXUnsavedFile &cxUnsavedFile)
+{
+ for (const FileContainer &fileContainer : fileContainers)
+ if (fileContainer == cxUnsavedFile)
+ return true;
+
+ return false;
+}
+
+MATCHER_P(HasUnsavedFiles, fileContainers, "")
+{
+ if (arg.unsavedFilesCount() != fileContainers.size()) {
+ *result_listener << "unsaved count is " << arg.unsavedFilesCount() << " and not " << fileContainers.size();
+ return false;
+ }
+
+ for (const CXUnsavedFile &cxUnsavedFile : arg.cxUnsavedFileVector()) {
+ if (!fileContainersContainsCxUnsavedFile(fileContainers, cxUnsavedFile))
+ return false;
+ }
+
+ return true;
+}
+
+class UnsavedFiles : public ::testing::Test
+{
+protected:
+ void TearDown() override;
+
+protected:
+ ::UnsavedFiles unsavedFiles;
+};
+
+void UnsavedFiles::TearDown()
+{
+ unsavedFiles.clear();
+}
+
+TEST_F(UnsavedFiles, DoNothingForUpdateWithNormalFile)
+{
+ QVector<FileContainer> fileContainers({FileContainer(Utf8StringLiteral("file.cpp"))});
+
+ unsavedFiles.update(fileContainers);
+
+ ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>()));
+}
+
+TEST_F(UnsavedFiles, AddUnsavedFileForUpdateWithUnsavedContent)
+{
+ QVector<FileContainer> fileContainers({FileContainer(Utf8StringLiteral("file.cpp")),
+ FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo"), true)});
+ unsavedFiles.update(fileContainers);
+
+ ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>({FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo"), true)})));
+}
+
+TEST_F(UnsavedFiles, RemoveUnsavedFileForUpdateWithUnsavedContent)
+{
+ QVector<FileContainer> fileContainers({FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo"), true),
+ FileContainer(Utf8StringLiteral("file.cpp"))});
+
+ unsavedFiles.update(fileContainers);
+
+ ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>()));
+}
+
+TEST_F(UnsavedFiles, ExchangeUnsavedFileForUpdateWithUnsavedContent)
+{
+ QVector<FileContainer> fileContainers({FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo"), true),
+ FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo2"), true)});
+ unsavedFiles.update(fileContainers);
+
+ ASSERT_THAT(unsavedFiles, HasUnsavedFiles(QVector<FileContainer>({FileContainer(Utf8StringLiteral("file.cpp"), Utf8StringLiteral("foo2"), true)})));
+}
+
+}
+
+
+
diff --git a/tests/unit/codemodelbackend/unittest/utf8test.cpp b/tests/unit/codemodelbackend/unittest/utf8test.cpp
index 7ab10f0a2a..19b33fcbc0 100644
--- a/tests/unit/codemodelbackend/unittest/utf8test.cpp
+++ b/tests/unit/codemodelbackend/unittest/utf8test.cpp
@@ -211,3 +211,11 @@ TEST(Utf8, PlusAssignmentOperator)
ASSERT_THAT(text, Utf8StringLiteral("foobar"));
}
+
+TEST(Utf8, CompareCharPointer)
+{
+ Utf8String text("foo", 3);
+
+ ASSERT_TRUE(text == "foo");
+ ASSERT_FALSE(text == "foo2");
+}