File indexing completed on 2024-03-24 04:36:55
0001 /***************************************************************************** 0002 * Copyright (c) 2007 Piyush verma <piyush.verma@gmail.com> * 0003 * Copyright (c) 2008,2010 Niko Sams <niko.sams@gmail.com> * 0004 * Copyright (c) 2010 Milian Wolff <mail@milianw.de> * 0005 * * 0006 * This program is free software; you can redistribute it and/or modify * 0007 * it under the terms of the GNU General Public License as published by * 0008 * the Free Software Foundation; either version 2 of the License, or * 0009 * (at your option) any later version. * 0010 * * 0011 * This program is distributed in the hope that it will be useful, * 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0014 * GNU General Public License for more details. * 0015 * * 0016 * You should have received a copy of the GNU General Public License * 0017 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0018 *****************************************************************************/ 0019 0020 #include "parsejob.h" 0021 0022 #include <QFile> 0023 #include <QMimeDatabase> 0024 #include <QReadWriteLock> 0025 #include <QReadLocker> 0026 #include <QThread> 0027 0028 #include <language/duchain/duchainlock.h> 0029 #include <language/duchain/duchain.h> 0030 #include <language/duchain/topducontext.h> 0031 #include <language/duchain/parsingenvironment.h> 0032 #include <language/duchain/declaration.h> 0033 #include <language/backgroundparser/urlparselock.h> 0034 0035 #include "debug.h" 0036 #include "parser/editorintegrator.h" 0037 #include "parser/parsesession.h" 0038 #include "csslanguagesupport.h" 0039 #include "duchain/builders/declarationbuilder.h" 0040 #include "parser/htmlparser.h" 0041 0042 0043 namespace Css 0044 { 0045 0046 ParseJob::ParseJob(const KDevelop::IndexedString& url, KDevelop::ILanguageSupport* languageSupport) 0047 : KDevelop::ParseJob(url, languageSupport) 0048 { 0049 qCDebug(KDEV_CSS); 0050 } 0051 0052 ParseJob::~ParseJob() 0053 { 0054 qCDebug(KDEV_CSS); 0055 } 0056 0057 void ParseJob::run(ThreadWeaver::JobPointer /*self*/, ThreadWeaver::Thread */*thread*/) 0058 { 0059 KDevelop::UrlParseLock urlLock(document()); 0060 0061 if ( !(minimumFeatures() & KDevelop::TopDUContext::ForceUpdate) ) { 0062 KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock()); 0063 bool needsUpdate = true; 0064 foreach(const KDevelop::ParsingEnvironmentFilePointer &file, KDevelop::DUChain::self()->allEnvironmentFiles(document())) { 0065 if (file->needsUpdate()) { 0066 needsUpdate = true; 0067 break; 0068 } else { 0069 needsUpdate = false; 0070 } 0071 } 0072 if (!needsUpdate) { 0073 qCDebug(KDEV_CSS) << "Already up to date" << document().str(); 0074 return; 0075 } 0076 } 0077 0078 qCDebug(KDEV_CSS) << "parsing" << document().str(); 0079 0080 KDevelop::ProblemPointer p = readContents(); 0081 if (p) { 0082 //TODO: associate problem with topducontext 0083 return abortJob();; 0084 } 0085 0086 QList<HtmlParser::Part> parts; 0087 0088 QMimeDatabase db; 0089 if (db.mimeTypeForUrl(document().toUrl()).name() == "text/css") { 0090 HtmlParser::Part part; 0091 part.kind = HtmlParser::Part::Standalone; 0092 part.contents = contents().contents; 0093 part.range.start() = {0, 0}; 0094 //part.range.end = TODO (needed?) 0095 parts << part; 0096 } else { 0097 HtmlParser p; 0098 p.setContents(contents().contents); 0099 parts = p.parse(); 0100 if (parts.isEmpty()) { 0101 parts << HtmlParser::Part(); //empty part 0102 } 0103 } 0104 Q_ASSERT(!parts.isEmpty()); 0105 0106 HtmlAst *fileAst = new HtmlAst; 0107 fileAst->kind = HtmlAst::KIND; 0108 foreach (const HtmlParser::Part &part, parts) { 0109 ParseSession *session = new ParseSession; 0110 session->setCurrentDocument(document()); 0111 session->setOffset(KDevelop::CursorInRevision::castFromSimpleCursor(part.range.start())); 0112 session->setContents(part.contents); 0113 if (part.kind != HtmlParser::Part::InlineStyle) { 0114 StyleElementAst *el = new StyleElementAst; 0115 el->kind = StyleElementAst::KIND; 0116 StartAst* ast = nullptr; 0117 session->parse(&ast); 0118 el->start = ast; 0119 el->session = session; 0120 fileAst->elements << el; 0121 } else { 0122 InlineStyleAst *el = new InlineStyleAst; 0123 el->kind = InlineStyleAst::KIND; 0124 DeclarationListAst* ast = nullptr; 0125 session->parse(&ast); 0126 el->declarationList = ast; 0127 el->session = session; 0128 fileAst->elements << el; 0129 } 0130 0131 if (abortRequested()) 0132 { 0133 return abortJob(); 0134 } 0135 } 0136 0137 KDevelop::ReferencedTopDUContext top; 0138 { 0139 KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock()); 0140 top = KDevelop::DUChain::self()->chainForDocument(document()); 0141 } 0142 if (top) { 0143 qCDebug(KDEV_CSS) << "re-compiling" << document().str(); 0144 KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock()); 0145 top->clearImportedParentContexts(); 0146 top->parsingEnvironmentFile()->clearModificationRevisions(); 0147 top->clearProblems(); 0148 } else { 0149 qCDebug(KDEV_CSS) << "compiling" << document().str(); 0150 } 0151 0152 QReadLocker parseLock(languageSupport()->parseLock()); 0153 0154 EditorIntegrator editor; 0155 DeclarationBuilder builder; 0156 builder.setEditor(&editor); 0157 top = builder.build(document(), fileAst, top); 0158 qCDebug(KDEV_CSS) << top; 0159 Q_ASSERT(top); 0160 0161 foreach (AstNode *el, fileAst->elements) { 0162 0163 ParseSession *session = nullptr; 0164 if (el->kind == StyleElementAst::KIND) { 0165 session = static_cast<StyleElementAst*>(el)->session; 0166 static_cast<StyleElementAst*>(el)->session = nullptr; //deleted below 0167 } else if (el->kind == InlineStyleAst::KIND) { 0168 session = static_cast<InlineStyleAst*>(el)->session; 0169 static_cast<InlineStyleAst*>(el)->session = nullptr; //deleted below 0170 } 0171 Q_ASSERT(session); 0172 foreach(const KDevelop::ProblemPointer &p, session->problems()) { 0173 KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock()); 0174 top->addProblem(p); 0175 } 0176 delete session; 0177 0178 if (abortRequested()) { 0179 return abortJob(); 0180 } 0181 delete el; 0182 } 0183 delete fileAst; 0184 setDuChain(top); 0185 0186 KDevelop::DUChainWriteLocker lock(KDevelop::DUChain::lock()); 0187 0188 top->setFeatures(minimumFeatures()); 0189 KDevelop::ParsingEnvironmentFilePointer file = top->parsingEnvironmentFile(); 0190 0191 QFileInfo fileInfo(document().str()); 0192 QDateTime lastModified = fileInfo.lastModified(); 0193 file->setModificationRevision(contents().modification); 0194 KDevelop::DUChain::self()->updateContextEnvironment( top->topContext(), file.data() ); 0195 KDevelop::DUChain::self()->emitUpdateReady(document(), top); 0196 } 0197 0198 } 0199 0200 // kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on; auto-insert-doxygen on