File indexing completed on 2024-04-28 04:37:35
0001 /* 0002 SPDX-FileCopyrightText: 2010 Niko Sams <niko.sams@gmail.com> 0003 SPDX-FileCopyrightText: 2011 Milian Wolff <mail@milianw.de> 0004 0005 SPDX-License-Identifier: LGPL-2.0-only 0006 */ 0007 0008 #include "testfile.h" 0009 0010 #include "testproject.h" 0011 0012 #include <QTemporaryFile> 0013 #include <QElapsedTimer> 0014 #include <QTest> 0015 0016 #include <language/duchain/duchainlock.h> 0017 #include <language/duchain/duchain.h> 0018 #include <language/backgroundparser/backgroundparser.h> 0019 #include <interfaces/icore.h> 0020 #include <interfaces/idocumentcontroller.h> 0021 #include <interfaces/ilanguagecontroller.h> 0022 #include <project/projectmodel.h> 0023 0024 using namespace KDevelop; 0025 0026 class KDevelop::TestFilePrivate 0027 { 0028 public: 0029 TestFilePrivate() 0030 { 0031 } 0032 0033 void updateReady(const IndexedString& _url, const ReferencedTopDUContext& _topContext) 0034 { 0035 Q_ASSERT(_url == url); 0036 Q_UNUSED(_url); 0037 topContext = _topContext; 0038 ready = true; 0039 } 0040 0041 void init(const QString& fileName, const QString& contents, TestProject* _project) 0042 { 0043 file = fileName; 0044 0045 setFileContents(contents); 0046 0047 QFileInfo info(file); 0048 Q_ASSERT(info.exists()); 0049 Q_ASSERT(info.isFile()); 0050 url = IndexedString(info.absoluteFilePath()); 0051 0052 project = _project; 0053 if (project) { 0054 fileItem.reset(new ProjectFileItem(_project, Path(file), _project->projectItem())); 0055 } 0056 } 0057 0058 void setFileContents(const QString& contents) 0059 { 0060 QFile file(this->file); 0061 file.open(QIODevice::WriteOnly | QIODevice::Truncate); 0062 Q_ASSERT(file.isOpen()); 0063 Q_ASSERT(file.isWritable()); 0064 file.write(contents.toUtf8()); 0065 ready = false; 0066 } 0067 0068 QString file; 0069 QString suffix; 0070 bool ready = false; 0071 ReferencedTopDUContext topContext; 0072 IndexedString url; 0073 TestProject* project; 0074 QScopedPointer<ProjectFileItem> fileItem; 0075 bool keepDUChainData = false; 0076 }; 0077 0078 TestFile::TestFile(const QString& contents, const QString& fileExtension, 0079 TestProject* project, const QString& dir) 0080 : d_ptr(new TestFilePrivate()) 0081 { 0082 Q_D(TestFile); 0083 0084 d->suffix = QLatin1Char('.') + fileExtension; 0085 0086 QTemporaryFile file((!dir.isEmpty() ? dir : QDir::tempPath()) + QLatin1String("/testfile_XXXXXX") + d->suffix); 0087 file.setAutoRemove(false); 0088 file.open(); 0089 Q_ASSERT(file.isOpen()); 0090 0091 d->init(file.fileName(), contents, project); 0092 } 0093 0094 TestFile::TestFile(const QString& contents, const QString& fileExtension, const TestFile* base) 0095 : d_ptr(new TestFilePrivate) 0096 { 0097 Q_D(TestFile); 0098 0099 QString fileName = base->d_func()->file.mid(0, base->d_func()->file.length() - base->d_func()->suffix.length()); 0100 d->suffix = QLatin1Char('.') + fileExtension; 0101 fileName += d->suffix; 0102 d->init(fileName, contents, base->d_func()->project); 0103 } 0104 0105 TestFile::TestFile(const QString& contents, const QString& fileExtension, const QString& fileName, 0106 KDevelop::TestProject* project, const QString& dir) 0107 : d_ptr(new TestFilePrivate) 0108 { 0109 Q_D(TestFile); 0110 0111 d->suffix = QLatin1Char('.') + fileExtension; 0112 const QString file = (!dir.isEmpty() ? dir : QDir::tempPath()) 0113 + QLatin1Char('/') + fileName + d->suffix; 0114 d->init(file, contents, project); 0115 } 0116 0117 0118 TestFile::~TestFile() 0119 { 0120 Q_D(TestFile); 0121 0122 if (auto* document = ICore::self()->documentController()->documentForUrl(d->url.toUrl())) { 0123 document->close(KDevelop::IDocument::Discard); 0124 } 0125 0126 auto backgroundParser = ICore::self()->languageController()->backgroundParser(); 0127 backgroundParser->removeDocument(d->url, this); 0128 QTRY_VERIFY(!backgroundParser->parseJobForDocument(d->url)); 0129 0130 if (d->topContext && !d->keepDUChainData) { 0131 DUChainWriteLocker lock; 0132 DUChain::self()->removeDocumentChain(d->topContext.data()); 0133 } 0134 QFile::remove(d->file); 0135 } 0136 0137 IndexedString TestFile::url() const 0138 { 0139 Q_D(const TestFile); 0140 0141 return d->url; 0142 } 0143 0144 void TestFile::parse(TopDUContext::Features features, int priority) 0145 { 0146 Q_D(TestFile); 0147 0148 d->ready = false; 0149 DUChain::self()->updateContextForUrl(d->url, features, this, priority); 0150 } 0151 0152 bool TestFile::parseAndWait(TopDUContext::Features features, int priority, int timeout) 0153 { 0154 parse(features, priority); 0155 return waitForParsed(timeout); 0156 } 0157 0158 bool TestFile::waitForParsed(int timeout) 0159 { 0160 Q_D(TestFile); 0161 0162 if (!d->ready) { 0163 // optimize: we don't want to wait the usual timeout before parsing documents here 0164 ICore::self()->languageController()->backgroundParser()->parseDocuments(); 0165 } 0166 QElapsedTimer t; 0167 t.start(); 0168 while (!d->ready && t.elapsed() < timeout) { 0169 QTest::qWait(10); 0170 } 0171 return d->ready; 0172 } 0173 0174 bool TestFile::isReady() const 0175 { 0176 Q_D(const TestFile); 0177 0178 return d->ready; 0179 } 0180 0181 ReferencedTopDUContext TestFile::topContext() 0182 { 0183 Q_D(TestFile); 0184 0185 waitForParsed(); 0186 return d->topContext; 0187 } 0188 0189 void TestFile::setFileContents(const QString& contents) 0190 { 0191 Q_D(TestFile); 0192 0193 d->setFileContents(contents); 0194 } 0195 0196 QString TestFile::fileContents() const 0197 { 0198 Q_D(const TestFile); 0199 0200 QFile file(d->file); 0201 file.open(QIODevice::ReadOnly); 0202 Q_ASSERT(file.isOpen()); 0203 Q_ASSERT(file.isReadable()); 0204 return QString::fromUtf8(file.readAll()); 0205 } 0206 0207 void TestFile::setKeepDUChainData(bool keep) 0208 { 0209 Q_D(TestFile); 0210 0211 d->keepDUChainData = keep; 0212 } 0213 0214 bool TestFile::keepDUChainData() const 0215 { 0216 Q_D(const TestFile); 0217 0218 return d->keepDUChainData; 0219 } 0220 0221 #include "moc_testfile.cpp"