QVector<rpp::pp_macro*> computeGccStandardMacros(bool withStdCpp0x = true) { QVector<rpp::pp_macro*> ret; //Get standard macros from gcc KProcess proc; proc.setOutputChannelMode(KProcess::MergedChannels); // The output of the following gcc commands is several line in the format: // "#define MACRO [definition]", where definition may or may not be present. // Parsing each line sequentially, we can easily build the macro set. proc << "gcc"; if (withStdCpp0x) { // see also: https://bugs.kde.org/show_bug.cgi?id=298252 proc << "-std=c++0x"; } proc << "-xc++" << "-E" << "-dM" <<NULL_DEVICE; if (proc.execute(5000) == 0) { QString line; while (proc.canReadLine()) { QByteArray buff = proc.readLine(); if (!buff.isEmpty()) { line = buff; if (line.startsWith("#define ")) { line = line.right(line.length() - 8).trimmed(); int pos = line.indexOf(' '); ret.append(new rpp::pp_macro); rpp::pp_macro& macro(*ret.back()); if (pos != -1) { macro.name = IndexedString( line.left(pos) ); macro.setDefinitionText( line.right(line.length() - pos - 1).toUtf8() ); } else { macro.name = IndexedString( line ); } } } } } else if (withStdCpp0x) { // fallback to macro computation without -std=c++0x arg for old gcc versions return computeGccStandardMacros(false); } else { kDebug(9007) <<"Unable to read standard c++ macro definitions from gcc:" <<QString(proc.readAll()) ; } return ret; }
void GoStructureType::setPrettyName(QString name) { if(name.size() > 40) { name = name.left(39); name.append("..."); } d_func_dynamic()->m_prettyName = IndexedString(name); }
IndexedString AbstractFunctionDeclaration::defaultParameterForArgument(int index) const { FunctionType::Ptr fType = dynamic_cast<const Declaration*>(this)->type<FunctionType>(); if(fType && index >= 0 && index < fType->arguments().size()) { index -= (fType->arguments().size() - defaultParametersSize()); if(index >= 0 && index < (int)defaultParametersSize()) return defaultParameters()[index]; } return IndexedString(); }
InsertArtificialCodeRepresentation::InsertArtificialCodeRepresentation(const IndexedString& file, const QString& text) : m_file(file) { if(m_file.toUrl().isRelative()) { m_file = IndexedString(CodeRepresentation::artificialUrl(file.str())); int idx = 0; while(artificialStrings.contains(m_file)) { ++idx; m_file = IndexedString(CodeRepresentation::artificialUrl(QString("%1_%2").arg(idx).arg(file.str()))); } } Q_ASSERT(!artificialStrings.contains(m_file)); artificialStrings.insert(m_file, KSharedPtr<ArtificialStringData>(new ArtificialStringData(text))); }
InsertArtificialCodeRepresentation::InsertArtificialCodeRepresentation(const IndexedString& file, const QString& text) : m_file(file) { // make it simpler to use this by converting relative strings into artificial paths if(QUrl(m_file.str()).isRelative()) { m_file = IndexedString(CodeRepresentation::artificialPath(file.str())); int idx = 0; while(artificialStrings.contains(m_file)) { ++idx; m_file = IndexedString(CodeRepresentation::artificialPath(QStringLiteral("%1_%2").arg(idx).arg(file.str()))); } } Q_ASSERT(!artificialStrings.contains(m_file)); artificialStrings.insert(m_file, QExplicitlySharedDataPointer<ArtificialStringData>(new ArtificialStringData(text))); }
void NameCompiler::visitUnqualifiedName(UnqualifiedNameAST *node) { IndexedString tmp_name; if (node->id) tmp_name = m_session->token_stream->token(node->id).symbol(); if (node->tilde) tmp_name = IndexedString('~' + tmp_name.byteArray()); if (OperatorFunctionIdAST *op_id = node->operator_id) { #if defined(__GNUC__) /* FIXME: unimplemented */ #endif static QString operatorString("operator"); QString tmp = operatorString; if (op_id->op && op_id->op->op) tmp += decode(m_session, op_id->op, true); else tmp += QLatin1String("{...cast...}"); tmp_name = IndexedString(tmp); m_typeSpecifier = op_id->type_specifier; } m_currentIdentifier = tmp_name.str(); m_name.push_back(m_currentIdentifier); if (node->template_arguments) { visitNodes(this, node->template_arguments); }/*else if(node->end_token == node->start_token + 3 && node->id == node->start_token && m_session->token_stream->token(node->id+1).symbol() == KDevelop::IndexedString('<')) { ///@todo Represent this nicer in the AST ///It's probably a type-specifier with instantiation of the default-parameter, like "Bla<>". m_currentIdentifier.appendTemplateIdentifier( IndexedTypeIdentifier() ); }*/ }
void TestParseJob::testSimpleHtml() { TopDUContext::Features features = TopDUContext::VisibleDeclarationsAndContexts; TestProject* project = new TestProject; m_projectController->closeAllProjects(); m_projectController->addProject(project); TestFile f("<html><style>a { color: red; }</style></html>", "html", project); f.parse(features); ReferencedTopDUContext top = f.topContext(); DUChainReadLocker lock; QVERIFY(top); QVERIFY(top->parsingEnvironmentFile()->language() == IndexedString("Css")); QCOMPARE(top->childContexts().count(), 1); }
EditorCodeRepresentation(KTextEditor::Document* document) : m_document(document) { m_url = IndexedString(m_document->url()); }
ParseJob* createParseJob(const KUrl& url, TopDUContext::Features features, QList<QPointer<QObject> > notifyWhenReady) { QList<ILanguage*> languages = m_languageController->languagesForUrl(url); foreach (ILanguage* language, languages) { if(!language) { kWarning() << "got zero language for" << url; continue; } if(!language->languageSupport()) { kWarning() << "language has no language support assigned:" << language->name(); continue; } ParseJob* job = language->languageSupport()->createParseJob(url); if (!job) { continue; // Language part did not produce a valid ParseJob. } job->setMinimumFeatures(features); job->setBackgroundParser(m_parser); job->setNotifyWhenReady(notifyWhenReady); QObject::connect(job, SIGNAL(done(ThreadWeaver::Job*)), m_parser, SLOT(parseComplete(ThreadWeaver::Job*))); QObject::connect(job, SIGNAL(failed(ThreadWeaver::Job*)), m_parser, SLOT(parseComplete(ThreadWeaver::Job*))); QObject::connect(job, SIGNAL(progress(KDevelop::ParseJob*, float, QString)), m_parser, SLOT(parseProgress(KDevelop::ParseJob*, float, QString)), Qt::QueuedConnection); m_parseJobs.insert(url, job); ++m_maxParseJobs; // TODO more thinking required here to support multiple parse jobs per url (where multiple language plugins want to parse) return job; } if(languages.isEmpty()) kDebug() << "found no languages for url" << url; else kDebug() << "could not create parse-job for url" << url; //Notify that we failed typedef QPointer<QObject> Notify; foreach(const Notify& n, notifyWhenReady) if(n) QMetaObject::invokeMethod(n, "updateReady", Qt::DirectConnection, Q_ARG(KDevelop::IndexedString, IndexedString(url)), Q_ARG(KDevelop::ReferencedTopDUContext, ReferencedTopDUContext())); return 0; }
seec::Maybe<IndexedString> IndexedString::from(UnicodeString const &String) { if (String.isBogus()) return seec::Maybe<IndexedString>(); UnicodeString const NeedleStart("@["); UnicodeString const NeedleEscape("@[["); UnicodeString const NeedleEnd("]"); UnicodeString CleanedString; // String with index indicators removed. std::multimap<UnicodeString, Needle> Needles; std::vector<std::pair<UnicodeString, int32_t>> IndexStack; int32_t SearchFrom = 0; // Current offset in String. int32_t FoundStart; // Position of matched index indicator. while ((FoundStart = String.indexOf(NeedleStart, SearchFrom)) != -1) { // Copy all the literal string data. CleanedString.append(String, SearchFrom, FoundStart - SearchFrom); // Check if this is an escape sequence. if (String.compare(FoundStart, NeedleEscape.length(), NeedleEscape) == 0) { CleanedString.append(NeedleStart); SearchFrom = FoundStart + NeedleEscape.length(); continue; } // Find the end of this sequence. int32_t FoundEnd = String.indexOf(NeedleEnd, SearchFrom); if (FoundEnd == -1) return seec::Maybe<IndexedString>(); if (FoundEnd == FoundStart + NeedleStart.length()) { // This is a closing sequence. if (IndexStack.size() == 0) return seec::Maybe<IndexedString>(); // Pop the starting details of the last-opened sequence. auto const Start = IndexStack.back(); IndexStack.pop_back(); // Store the needle for this sequence. Needles.insert(std::make_pair(Start.first, Needle(Start.second, CleanedString.countChar32()))); } else { // This is an opening sequence. int32_t const NameStart = FoundStart + NeedleStart.length(); int32_t const NameLength = FoundEnd - NameStart; IndexStack.emplace_back(UnicodeString(String, NameStart, NameLength), CleanedString.countChar32()); } SearchFrom = FoundEnd + NeedleEnd.length(); } // Copy all remaining literal data. CleanedString.append(String, SearchFrom, String.length() - SearchFrom); return IndexedString(std::move(CleanedString), std::move(Needles)); }
Preprocessor::Preprocessor(const QList<QDir>& includeDirs, const QStringList& defines, const QFileInfo& file) : m_includeDirs(includeDirs), m_defines(defines), m_file(file) { pp = new rpp::pp(this); pp->setEnvironment(new GeneratorEnvironment(pp)); if (file.exists()) m_fileStack.push(file); m_topBlock = new rpp::MacroBlock(0); // some basic definitions rpp::pp_macro* exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__cplusplus"); exportMacro->definition.append(IndexedString('1')); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__GNUC__"); exportMacro->definition.append(IndexedString('4')); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__GNUC_MINOR__"); exportMacro->definition.append(IndexedString('1')); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); exportMacro = new rpp::pp_macro; #if defined(Q_OS_LINUX) exportMacro->name = IndexedString("__linux__"); #elif defined(Q_OS_WIN32) exportMacro->name = IndexedString("WIN32"); #elif defined(Q_OS_WIN64) exportMacro->name = IndexedString("WIN64"); #elif defined(Q_OS_DARWIN) exportMacro->name = IndexedString("__APPLE__"); #elif defined(Q_OS_SOLARIS) exportMacro->name = IndexedString("__sun"); #else // fall back to linux if nothing matches exportMacro->name = IndexedString("__linux__"); #endif exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); #if defined(Q_OS_DARWIN64) exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__LP64__"); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); #endif #if (defined(QT_ARCH_ARM) || defined (QT_ARCH_ARMV6)) && !defined(QT_NO_ARM_EABI) exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__ARM_EABI__"); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); #endif // ansidecl.h will define macros for keywords if we don't define __STDC__ exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__STDC__"); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString("__SMOKEGEN_RUN__"); exportMacro->definition.append(IndexedString('1')); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); foreach (QString define, defines) { exportMacro = new rpp::pp_macro; exportMacro->name = IndexedString(define); exportMacro->function_like = false; exportMacro->variadics = false; m_topBlock->setMacro(exportMacro); }
void CodeCompletionWorker::computeCompletions(KDevelop::DUContextPointer context, const KTextEditor::Cursor& position, QString followingText, const KTextEditor::Range& _contextRange, const QString& _contextText) { KTextEditor::Range contextRange(_contextRange); QString contextText(_contextText); TopDUContextPointer topContext; { DUChainReadLocker lock(DUChain::lock()); if(context) topContext = TopDUContextPointer(context->topContext()); if(!topContext) return; if(!topContext->parsingEnvironmentFile() || topContext->parsingEnvironmentFile()->language() != IndexedString("C++")) { kDebug() << "top-context has wrong language:"; return; } } Cpp::TypeConversionCacheEnabler enableConversionCache; KDevelop::CodeCompletionWorker::computeCompletions(context, position, followingText, contextRange, contextText); }