QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString & origEntry) { QString entry = trimWildcards(origEntry); QList<Locator::FilterEntry> goodEntries; QList<Locator::FilterEntry> betterEntries; QStringMatcher matcher(entry, Qt::CaseInsensitive); const QChar asterisk = QLatin1Char('*'); QRegExp regexp(asterisk + entry + asterisk, Qt::CaseInsensitive, QRegExp::Wildcard); if (!regexp.isValid()) return goodEntries; bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?'))); if (m_currentFileName.isEmpty()) return goodEntries; if (m_itemsOfCurrentDoc.isEmpty()) { Snapshot snapshot = m_modelManager->snapshot(); Document::Ptr thisDocument = snapshot.document(m_currentFileName); if (thisDocument) m_itemsOfCurrentDoc = search(thisDocument); } const Qt::CaseSensitivity caseSensitivityForPrefix = caseSensitivity(entry); foreach (const ModelItemInfo & info, m_itemsOfCurrentDoc) { if (future.isCanceled()) break; QString matchString = info.symbolName; if (info.type == ModelItemInfo::Declaration) matchString = ModelItemInfo::representDeclaration(info.symbolName, info.symbolType); else if (info.type == ModelItemInfo::Method) matchString += info.symbolType; if ((hasWildcard && regexp.exactMatch(matchString)) || (!hasWildcard && matcher.indexIn(matchString) != -1)) { QVariant id = qVariantFromValue(info); QString name = matchString; QString extraInfo = info.symbolScope; if (info.type == ModelItemInfo::Method) { if (info.unqualifiedNameAndScope(matchString, &name, &extraInfo)) name += info.symbolType; } Locator::FilterEntry filterEntry(this, name, id, info.icon); filterEntry.extraInfo = extraInfo; if (matchString.startsWith(entry, caseSensitivityForPrefix)) betterEntries.append(filterEntry); else goodEntries.append(filterEntry); } } // entries are unsorted by design! betterEntries += goodEntries; return betterEntries; }
void CppElementEvaluator::handleLookupItemMatch(const Snapshot &snapshot, const LookupItem &lookupItem, const LookupContext &context, const Scope *scope) { Symbol *declaration = lookupItem.declaration(); if (!declaration) { const QString &type = Overview().prettyType(lookupItem.type(), QString()); // special case for bug QTCREATORBUG-4780 if (scope && scope->isFunction() && lookupItem.type().match(scope->asFunction()->returnType())) { return; } m_element = QSharedPointer<CppElement>(new Unknown(type)); } else { const FullySpecifiedType &type = declaration->type(); if (declaration->isNamespace()) { m_element = QSharedPointer<CppElement>(new CppNamespace(declaration)); } else if (declaration->isClass() || declaration->isForwardClassDeclaration() || (declaration->isTemplate() && declaration->asTemplate()->declaration() && (declaration->asTemplate()->declaration()->isClass() || declaration->asTemplate()->declaration()->isForwardClassDeclaration()))) { LookupContext contextToUse = context; if (declaration->isForwardClassDeclaration()) if (Symbol *classDeclaration = m_symbolFinder.findMatchingClassDeclaration(declaration, snapshot)) { declaration = classDeclaration; const QString fileName = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()); const Document::Ptr declarationDocument = snapshot.document(fileName); if (declarationDocument != context.thisDocument()) contextToUse = LookupContext(declarationDocument, snapshot); } CppClass *cppClass = new CppClass(declaration); if (m_lookupBaseClasses) cppClass->lookupBases(declaration, contextToUse); if (m_lookupDerivedClasses) cppClass->lookupDerived(declaration, snapshot); m_element = QSharedPointer<CppElement>(cppClass); } else if (Enum *enumDecl = declaration->asEnum()) { m_element = QSharedPointer<CppElement>(new CppEnum(enumDecl)); } else if (EnumeratorDeclaration *enumerator = dynamic_cast<EnumeratorDeclaration *>(declaration)) { m_element = QSharedPointer<CppElement>(new CppEnumerator(enumerator)); } else if (declaration->isTypedef()) { m_element = QSharedPointer<CppElement>(new CppTypedef(declaration)); } else if (declaration->isFunction() || (type.isValid() && type->isFunctionType()) || declaration->isTemplate()) { m_element = QSharedPointer<CppElement>(new CppFunction(declaration)); } else if (declaration->isDeclaration() && type.isValid()) { m_element = QSharedPointer<CppElement>( new CppVariable(declaration, context, lookupItem.scope())); } else { m_element = QSharedPointer<CppElement>(new CppDeclarableElement(declaration)); } } }
// TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this function static Document::Ptr findDefinition(Function *functionDeclaration, int *line) { CppTools::CppModelManager *cppModelManager = CppTools::CppModelManager::instance(); const Snapshot snapshot = cppModelManager->snapshot(); CppTools::SymbolFinder symbolFinder; if (Function *fun = symbolFinder.findMatchingDefinition(functionDeclaration, snapshot)) { if (line) *line = fun->line(); return snapshot.document(QString::fromUtf8(fun->fileName(), fun->fileNameLength())); } return Document::Ptr(); }
// TODO: remove me, this is taken from cppeditor.cpp. Find some common place for this method static Document::Ptr findDefinition(Function *functionDeclaration, int *line) { if (CppModelManagerInterface *cppModelManager = CppModelManagerInterface::instance()) { const Snapshot snapshot = cppModelManager->snapshot(); if (Symbol *def = snapshot.findMatchingDefinition(functionDeclaration)) { if (line) *line = def->line(); return snapshot.document(QString::fromUtf8(def->fileName(), def->fileNameLength())); } } return Document::Ptr(); }
QList<Locator::FilterEntry> CppCurrentDocumentFilter::matchesFor(QFutureInterface<Locator::FilterEntry> &future, const QString & origEntry) { QString entry = trimWildcards(origEntry); QList<Locator::FilterEntry> goodEntries; QList<Locator::FilterEntry> betterEntries; QStringMatcher matcher(entry, Qt::CaseInsensitive); const QChar asterisk = QLatin1Char('*'); QRegExp regexp(asterisk + entry + asterisk, Qt::CaseInsensitive, QRegExp::Wildcard); if (!regexp.isValid()) return goodEntries; bool hasWildcard = (entry.contains(asterisk) || entry.contains(QLatin1Char('?'))); if (m_currentFileName.isEmpty()) return goodEntries; if (m_itemsOfCurrentDoc.isEmpty()) { Snapshot snapshot = m_modelManager->snapshot(); Document::Ptr thisDocument = snapshot.document(m_currentFileName); if (thisDocument) m_itemsOfCurrentDoc = search(thisDocument); } foreach (const ModelItemInfo & info, m_itemsOfCurrentDoc) { if (future.isCanceled()) break; if ((hasWildcard && regexp.exactMatch(info.symbolName)) || (!hasWildcard && matcher.indexIn(info.symbolName) != -1)) { QString symbolName = info.symbolName;// + (info.type == ModelItemInfo::Declaration ? ";" : " {...}"); QVariant id = qVariantFromValue(info); Locator::FilterEntry filterEntry(this, symbolName, id, info.icon); filterEntry.extraInfo = info.symbolType; if (info.symbolName.startsWith(entry)) betterEntries.append(filterEntry); else goodEntries.append(filterEntry); } } // entries are unsorted by design! betterEntries += goodEntries; return betterEntries; }
void QmlTaskManager::collectMessages( QFutureInterface<FileErrorMessages> &future, Snapshot snapshot, QList<ModelManagerInterface::ProjectInfo> projectInfos, ViewerContext vContext, bool updateSemantic) { foreach (const ModelManagerInterface::ProjectInfo &info, projectInfos) { QHash<QString, QList<DiagnosticMessage> > linkMessages; ContextPtr context; if (updateSemantic) { Link link(snapshot, vContext, snapshot.libraryInfo(info.qtImportsPath)); context = link(&linkMessages); } foreach (const QString &fileName, info.sourceFiles) { Document::Ptr document = snapshot.document(fileName); if (!document) continue; FileErrorMessages result; result.fileName = fileName; if (Document::isFullySupportedLanguage(document->language())) { result.tasks = convertToTasks(document->diagnosticMessages(), Utils::FileName::fromString(fileName), Core::Id(Constants::TASK_CATEGORY_QML)); if (updateSemantic) { result.tasks += convertToTasks(linkMessages.value(fileName), Utils::FileName::fromString(fileName), Core::Id(Constants::TASK_CATEGORY_QML_ANALYSIS)); Check checker(document, context); result.tasks += convertToTasks(checker(), Utils::FileName::fromString(fileName), Core::Id(Constants::TASK_CATEGORY_QML_ANALYSIS)); } } if (!result.tasks.isEmpty()) future.reportResult(result); if (future.isCanceled()) break; } }
QList<CppTools::IndexItem::Ptr> CppCurrentDocumentFilter::itemsOfCurrentDocument() { QMutexLocker locker(&m_mutex); if (m_currentFileName.isEmpty()) return QList<CppTools::IndexItem::Ptr>(); if (m_itemsOfCurrentDoc.isEmpty()) { const Snapshot snapshot = m_modelManager->snapshot(); if (const Document::Ptr thisDocument = snapshot.document(m_currentFileName)) { IndexItem::Ptr rootNode = search(thisDocument); rootNode->visitAllChildren([&](const IndexItem::Ptr &info) -> IndexItem::VisitorResult { m_itemsOfCurrentDoc.append(info); return IndexItem::Recurse; }); } } return m_itemsOfCurrentDoc; }
void DependencyTable::build(const Snapshot &snapshot) { includesPerFile.clear(); files.clear(); fileIndex.clear(); includes.clear(); includeMap.clear(); const int documentCount = snapshot.size(); files.resize(documentCount); includeMap.resize(documentCount); int i = 0; for (Snapshot::const_iterator it = snapshot.begin(); it != snapshot.end(); ++it, ++i) { files[i] = it.key(); fileIndex[it.key()] = i; } for (int i = 0; i < files.size(); ++i) { const QString fileName = files.at(i); if (Document::Ptr doc = snapshot.document(files.at(i))) { QBitArray bitmap(files.size()); QList<int> directIncludes; const QStringList documentIncludes = doc->includedFiles(); includesPerFile.insert(fileName, documentIncludes); foreach (const QString &includedFile, documentIncludes) { int index = fileIndex.value(includedFile); if (index == -1) continue; else if (! directIncludes.contains(index)) directIncludes.append(index); bitmap.setBit(index, true); } includeMap[i] = bitmap; includes[i] = directIncludes; }
bool QtCreatorIntegration::navigateToSlot(const QString &objectName, const QString &signalSignature, const QStringList ¶meterNames, QString *errorMessage) { typedef QMap<int, Document::Ptr> DocumentMap; const Utils::FileName currentUiFile = FormEditorW::activeEditor()->document()->filePath(); #if 0 return Designer::Internal::navigateToSlot(currentUiFile.toString(), objectName, signalSignature, parameterNames, errorMessage); #endif // TODO: we should pass to findDocumentsIncluding an absolute path to generated .h file from ui. // Currently we are guessing the name of ui_<>.h file and pass the file name only to the findDocumentsIncluding(). // The idea is that the .pro file knows if the .ui files is inside, and the .pro file knows it will // be generating the ui_<>.h file for it, and the .pro file knows what the generated file's name and its absolute path will be. // So we should somehow get that info from project manager (?) const QFileInfo fi = currentUiFile.toFileInfo(); const QString uiFolder = fi.absolutePath(); const QString uicedName = "ui_" + fi.completeBaseName() + ".h"; // Retrieve code model snapshot restricted to project of ui file or the working copy. Snapshot docTable = CppTools::CppModelManager::instance()->snapshot(); Snapshot newDocTable; const Project *uiProject = SessionManager::projectForFile(currentUiFile); if (uiProject) { for (Snapshot::const_iterator i = docTable.begin(), ei = docTable.end(); i != ei; ++i) { const Project *project = SessionManager::projectForFile(i.key()); if (project == uiProject) newDocTable.insert(i.value()); } } else { const CppTools::WorkingCopy workingCopy = CppTools::CppModelManager::instance()->workingCopy(); const Utils::FileName configFileName = Utils::FileName::fromString(CppTools::CppModelManager::configurationFileName()); QHashIterator<Utils::FileName, QPair<QByteArray, unsigned> > it = workingCopy.iterator(); while (it.hasNext()) { it.next(); const Utils::FileName &fileName = it.key(); if (fileName != configFileName) newDocTable.insert(docTable.document(fileName)); } } docTable = newDocTable; // take all docs, find the ones that include the ui_xx.h. // Sort into a map, putting the ones whose path closely matches the ui-folder path // first in case there are project subdirectories that contain identical file names. const QList<Document::Ptr> docList = findDocumentsIncluding(docTable, uicedName, true); // change to false when we know the absolute path to generated ui_<>.h file DocumentMap docMap; for (const Document::Ptr &d : docList) { const QFileInfo docFi(d->fileName()); docMap.insert(qAbs(docFi.absolutePath().compare(uiFolder, Qt::CaseInsensitive)), d); } if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO << objectName << signalSignature << "Looking for " << uicedName << " returned " << docList.size(); if (docMap.isEmpty()) { *errorMessage = tr("No documents matching \"%1\" could be found.\nRebuilding the project might help.").arg(uicedName); return false; } QDesignerFormWindowInterface *fwi = FormEditorW::activeWidgetHost()->formWindow(); const QString uiClass = uiClassName(fwi->mainContainer()->objectName()); if (Designer::Constants::Internal::debug) qDebug() << "Checking docs for " << uiClass; // Find the class definition (ui class defined as member or base class) // in the file itself or in the directly included files (order 1). QString namespaceName; const Class *cl = 0; Document::Ptr doc; for (const Document::Ptr &d : qAsConst(docMap)) { LookupContext context(d, docTable); const ClassDocumentPtrPair cd = findClassRecursively(context, uiClass, 1u , &namespaceName); if (cd.first) { cl = cd.first; doc = cd.second; break; } } if (!cl) { *errorMessage = msgClassNotFound(uiClass, docList); return false; } Overview o; const QString className = namespaceName + o.prettyName(cl->name()); if (Designer::Constants::Internal::debug) qDebug() << "Found class " << className << doc->fileName(); const QString functionName = "on_" + objectName + '_' + signalSignature; const QString functionNameWithParameterNames = addParameterNames(functionName, parameterNames); if (Designer::Constants::Internal::debug) qDebug() << Q_FUNC_INFO << "Found " << uiClass << doc->fileName() << " checking " << functionName << functionNameWithParameterNames; int line = 0; Document::Ptr sourceDoc; if (Function *fun = findDeclaration(cl, functionName)) { sourceDoc = findDefinition(fun, &line); if (!sourceDoc) { // add function definition to cpp file sourceDoc = addDefinition(docTable, doc->fileName(), className, functionNameWithParameterNames, &line); } } else { // add function declaration to cl CppTools::WorkingCopy workingCopy = CppTools::CppModelManager::instance()->workingCopy(); const QString fileName = doc->fileName(); getParsedDocument(fileName, workingCopy, docTable); addDeclaration(docTable, fileName, cl, functionNameWithParameterNames); // add function definition to cpp file sourceDoc = addDefinition(docTable, fileName, className, functionNameWithParameterNames, &line); } if (!sourceDoc) { *errorMessage = tr("Unable to add the method definition."); return false; } // jump to function definition, position within code Core::EditorManager::openEditorAt(sourceDoc->fileName(), line + 2, indentation); return true; }
void BuiltinEditorDocumentParser::updateHelper(const WorkingCopy &theWorkingCopy) { if (filePath().isEmpty()) return; const Configuration baseConfig = configuration(); const bool releaseSourceAndAST_ = releaseSourceAndAST(); State baseState = state(); ExtraState state = extraState(); WorkingCopy workingCopy = theWorkingCopy; bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged_ = false; CppModelManager *modelManager = CppModelManager::instance(); QByteArray configFile = modelManager->codeModelConfiguration(); ProjectPartHeaderPaths headerPaths; QStringList precompiledHeaders; QString projectConfigFile; LanguageFeatures features = LanguageFeatures::defaultFeatures(); baseState.projectPart = determineProjectPart(filePath(), baseConfig, baseState); if (state.forceSnapshotInvalidation) { invalidateSnapshot = true; state.forceSnapshotInvalidation = false; } if (const ProjectPart::Ptr part = baseState.projectPart) { configFile += part->toolchainDefines; configFile += overwrittenToolchainDefines(*part.data()); configFile += part->projectDefines; headerPaths = part->headerPaths; projectConfigFile = part->projectConfigFile; if (baseConfig.usePrecompiledHeaders) precompiledHeaders = part->precompiledHeaders; features = part->languageFeatures; } if (configFile != state.configFile) { state.configFile = configFile; invalidateSnapshot = true; invalidateConfig = true; } if (baseConfig.editorDefines != baseState.editorDefines) { baseState.editorDefines = baseConfig.editorDefines; invalidateSnapshot = true; editorDefinesChanged_ = true; } if (headerPaths != state.headerPaths) { state.headerPaths = headerPaths; invalidateSnapshot = true; } if (projectConfigFile != state.projectConfigFile) { state.projectConfigFile = projectConfigFile; invalidateSnapshot = true; } if (precompiledHeaders != state.precompiledHeaders) { state.precompiledHeaders = precompiledHeaders; invalidateSnapshot = true; } unsigned rev = 0; if (Document::Ptr doc = state.snapshot.document(filePath())) rev = doc->revision(); else invalidateSnapshot = true; Snapshot globalSnapshot = modelManager->snapshot(); if (invalidateSnapshot) { state.snapshot = Snapshot(); } else { // Remove changed files from the snapshot QSet<Utils::FileName> toRemove; foreach (const Document::Ptr &doc, state.snapshot) { const Utils::FileName fileName = Utils::FileName::fromString(doc->fileName()); if (workingCopy.contains(fileName)) { if (workingCopy.get(fileName).second != doc->editorRevision()) addFileAndDependencies(&state.snapshot, &toRemove, fileName); continue; } Document::Ptr otherDoc = globalSnapshot.document(fileName); if (!otherDoc.isNull() && otherDoc->revision() != doc->revision()) addFileAndDependencies(&state.snapshot, &toRemove, fileName); } if (!toRemove.isEmpty()) { invalidateSnapshot = true; foreach (const Utils::FileName &fileName, toRemove) state.snapshot.remove(fileName); } }
void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) { QMutexLocker locker(&m_mutex); if (m_fileInEditor.isEmpty()) return; bool invalidateSnapshot = false, invalidateConfig = false, editorDefinesChanged = false; CppModelManager *modelManager = dynamic_cast<CppModelManager *>(CppModelManagerInterface::instance()); QByteArray configFile = modelManager->codeModelConfiguration(); QStringList includePaths; QStringList frameworkPaths; QStringList precompiledHeaders; updateProjectPart(); if (m_forceSnapshotInvalidation) { invalidateSnapshot = true; m_forceSnapshotInvalidation = false; } if (m_projectPart) { configFile += m_projectPart->toolchainDefines; configFile += m_projectPart->projectDefines; includePaths = m_projectPart->includePaths; frameworkPaths = m_projectPart->frameworkPaths; if (m_usePrecompiledHeaders) precompiledHeaders = m_projectPart->precompiledHeaders; } if (configFile != m_configFile) { m_configFile = configFile; invalidateSnapshot = true; invalidateConfig = true; } if (m_editorDefinesChangedSinceLastUpdate) { invalidateSnapshot = true; editorDefinesChanged = true; m_editorDefinesChangedSinceLastUpdate = false; } if (includePaths != m_includePaths) { m_includePaths = includePaths; invalidateSnapshot = true; } if (frameworkPaths != m_frameworkPaths) { m_frameworkPaths = frameworkPaths; invalidateSnapshot = true; } if (precompiledHeaders != m_precompiledHeaders) { m_precompiledHeaders = precompiledHeaders; invalidateSnapshot = true; } unsigned rev = 0; if (Document::Ptr doc = document()) rev = doc->revision(); else invalidateSnapshot = true; Snapshot globalSnapshot = modelManager->snapshot(); if (invalidateSnapshot) { m_snapshot = Snapshot(); } else { // Remove changed files from the snapshot QSet<QString> toRemove; foreach (const Document::Ptr &doc, m_snapshot) { QString fileName = doc->fileName(); if (workingCopy.contains(fileName)) { if (workingCopy.get(fileName).second != doc->editorRevision()) addFileAndDependencies(&toRemove, fileName); continue; } Document::Ptr otherDoc = globalSnapshot.document(fileName); if (!otherDoc.isNull() && otherDoc->revision() != doc->revision()) addFileAndDependencies(&toRemove, fileName); } if (!toRemove.isEmpty()) { invalidateSnapshot = true; foreach (const QString &fileName, toRemove) m_snapshot.remove(fileName); }