bool DUChainItemData::execute( QString& /*filterText*/ ) { DUChainReadLocker lock;; Declaration* decl = m_item.m_item.data(); if(!decl) { return false; } if(m_openDefinition && FunctionDefinition::definition(decl)) { decl = FunctionDefinition::definition(decl); } QUrl url = decl->url().toUrl(); KTextEditor::Cursor cursor = decl->rangeInCurrentRevision().start(); DUContext* internal = decl->internalContext(); if(internal && (internal->type() == DUContext::Other || internal->type() == DUContext::Class)) { //Move into the body if(internal->range().end.line > internal->range().start.line) { cursor = KTextEditor::Cursor(internal->range().start.line+1, 0); //Move into the body } } lock.unlock(); ICore::self()->documentController()->openDocument( url, cursor ); return true; }
QPair<DUContext*, QualifiedIdentifier> ContextBuilder::findPrefixContext(const QualifiedIdentifier& id, KDevelop::SimpleCursor pos) { if(id.count() < 2) return qMakePair((DUContext*)0, QualifiedIdentifier()); QualifiedIdentifier prefixId(id); prefixId.pop(); DUContext* import = 0; { DUChainReadLocker lock(DUChain::lock()); QualifiedIdentifier currentScopeId = currentContext()->scopeIdentifier(true); QList<Declaration*> decls = currentContext()->findDeclarations(prefixId, pos); if(!decls.isEmpty()) { DUContext* classContext = decls.first()->logicalInternalContext(0); if(classContext && classContext->type() == DUContext::Class) { import = classContext; //Change the prefix-id so it respects namespace-imports prefixId = classContext->scopeIdentifier(true); if(prefixId.count() >= currentScopeId.count() && prefixId.left(currentScopeId.count()) == currentScopeId) prefixId = prefixId.mid(currentScopeId.count()); else kDebug() << "resolved bad prefix context. Should start with" << currentScopeId.toString() << "but is" << prefixId.toString(); } } } return qMakePair(import, prefixId); }
void ADLTypeVisitor::endVisit(const FunctionType * /*type*/) { // return type and argument types are handled by FunctionType::accept0 // here we process the namespace of the function name (or containing class), if any /* at the bottom of 3.4.2.2 we find the following: In addition, if the argument is the name or address of a set of overloaded functions and/or function tem- plates, its associated classes and namespaces are the union of those associated with each of the members of the set: the namespace in which the function or function template is defined and the classes and namespaces associated with its (non-dependent) parameter types and return type. */ if (m_helper.m_possibleFunctionName.data() && m_helper.m_possibleFunctionName.data()->isFunctionDeclaration()) { Declaration * declaration = m_helper.m_possibleFunctionName.data(); #ifdef DEBUG_ADL qCDebug(CPPDUCHAIN) << " function name = " << declaration->toString() << " ; identifier = " << declaration->qualifiedIdentifier().toString(); #endif // start going towards the global scope until we match an interesting name // note that calling addDeclarationScopeIdentifier does not work because for some reason // for function names DUContext::scopeIdentifier returns the function name instead of the // name of the function's scope DUContext* context = declaration->context(); while (context) { if (Declaration* decl = context->owner()) { if (context->type() == DUContext::Namespace) { m_helper.addAssociatedNamespace(decl->qualifiedIdentifier()); break; } else if (context->type() == DUContext::Class) { m_helper.addAssociatedClass(decl); break; } } context = context->parentContext(); } } }
void AdaptSignatureAction::execute() { ENSURE_CHAIN_NOT_LOCKED DUChainReadLocker lock; IndexedString url = m_otherSideTopContext->url(); lock.unlock(); m_otherSideTopContext = DUChain::self()->waitForUpdate(url, TopDUContext::AllDeclarationsContextsAndUses); if (!m_otherSideTopContext) { clangDebug() << "failed to update" << url.str(); return; } lock.lock(); Declaration* otherSide = m_otherSideId.getDeclaration(m_otherSideTopContext.data()); if (!otherSide) { clangDebug() << "could not find definition"; return; } DUContext* functionContext = DUChainUtils::getFunctionContext(otherSide); if (!functionContext) { clangDebug() << "no function context"; return; } if (!functionContext || functionContext->type() != DUContext::Function) { clangDebug() << "no correct function context"; return; } DocumentChangeSet changes; KTextEditor::Range parameterRange = ClangIntegration::DUChainUtils::functionSignatureRange(otherSide); QString newText = CodegenHelper::makeSignatureString(otherSide, m_newSignature, !m_editingDefinition); if (!m_editingDefinition) { // append a newline after the method signature in case the method definition follows newText += QLatin1Char('\n'); } DocumentChange changeParameters(functionContext->url(), parameterRange, QString(), newText); lock.unlock(); changeParameters.m_ignoreOldText = true; changes.addChange(changeParameters); changes.setReplacementPolicy(DocumentChangeSet::WarnOnFailedChange); DocumentChangeSet::ChangeResult result = changes.applyAllChanges(); if (!result) { KMessageBox::error(nullptr, i18n("Failed to apply changes: %1", result.m_failureReason)); } emit executed(this); foreach(RenameAction * renAct, m_renameActions) { renAct->execute(); } }
void CorrectionFileGenerator::addHint(const QString &typeCode, const QStringList &modules, Declaration *forDeclaration, CorrectionFileGenerator::HintType hintType) { if ( ! forDeclaration || ! forDeclaration->context() ) { qCWarning(KDEV_PYTHON_CODEGEN) << "Declaration does not have context!" << (forDeclaration ? forDeclaration->toString() : ""); return; } DUContext* context = forDeclaration->context(); if ( context->type() == DUContext::Function ) { auto otherImporters = context->importers(); if ( otherImporters.isEmpty() ) { return; } context = otherImporters.first(); } // We're in a class if the context of the declaration is a Class or if its // parent context is a class. This is because a function body has a context // of type Other. bool inClass = context->type() == DUContext::Class || (context->parentContext() && context->parentContext()->type() == DUContext::Class); // If the declaration is part of the function's arguments or it's parent // context is one of a function. bool inFunction = context->type() == DUContext::Function || (context->owner() && context->owner()->abstractType()->whichType() == AbstractType::TypeFunction); qCDebug(KDEV_PYTHON_CODEGEN) << "Are we in a class: " << inClass; qCDebug(KDEV_PYTHON_CODEGEN) << "Are we in a function: " << inFunction; QString enclosingClassIdentifier, enclosingFunctionIdentifier; if ( context->owner() ) { if ( inClass && inFunction ) { Declaration *functionDeclaration = context->owner(); enclosingClassIdentifier = functionDeclaration->context()->owner()->identifier().identifier().str(); enclosingFunctionIdentifier = functionDeclaration->identifier().identifier().str(); } else if ( inClass ) { enclosingClassIdentifier = context->owner()->identifier().identifier().str(); } else if ( inFunction ) { enclosingFunctionIdentifier = context->owner()->identifier().identifier().str(); } } qCDebug(KDEV_PYTHON_CODEGEN) << "Enclosing class: " << enclosingClassIdentifier; qCDebug(KDEV_PYTHON_CODEGEN) << "Enclosing function: " << enclosingFunctionIdentifier; QString declarationIdentifier = forDeclaration->identifier().identifier().str(); bool foundClassDeclaration = false; bool foundFunctionDeclaration = false; QString functionIdentifier; if ( hintType == FunctionReturnHint ) { functionIdentifier = declarationIdentifier; } else if ( hintType == LocalVariableHint ) { functionIdentifier = enclosingFunctionIdentifier; } int line = findStructureFor(enclosingClassIdentifier, functionIdentifier); if ( line == -1 ) { line = findStructureFor(enclosingClassIdentifier, QString()); } else if ( inFunction || hintType == FunctionReturnHint ) { foundFunctionDeclaration = true; } if ( line == -1 ) { line = findStructureFor(QString(), QString()); } else if ( inClass ) { foundClassDeclaration = true; } qCDebug(KDEV_PYTHON_CODEGEN) << "Found class declaration: " << foundClassDeclaration << enclosingClassIdentifier; qCDebug(KDEV_PYTHON_CODEGEN) << "Found function declaration: " << foundFunctionDeclaration << functionIdentifier; qCDebug(KDEV_PYTHON_CODEGEN) << "Line: " << line; int indentsForNextStatement = m_fileIndents->indentForLine(line); if ( foundClassDeclaration ) { indentsForNextStatement += DEFAULT_INDENT_LEVEL; } QStringList newCode; if ( inClass ) { if ( ! foundClassDeclaration ) { QString classDeclaration = createStructurePart(enclosingClassIdentifier, ClassType); classDeclaration.prepend(QString(indentsForNextStatement, ' ')); newCode.append(classDeclaration); indentsForNextStatement += DEFAULT_INDENT_LEVEL; } else { line++; } } if ( inFunction || hintType == FunctionReturnHint ) { if ( ! foundFunctionDeclaration ) { QString functionDeclaration; if ( inClass ) { functionDeclaration = createStructurePart(functionIdentifier, MemberFunctionType); } else { functionDeclaration = createStructurePart(functionIdentifier, FunctionType); } functionDeclaration.prepend(QString(indentsForNextStatement, ' ')); newCode.append(functionDeclaration); indentsForNextStatement += DEFAULT_INDENT_LEVEL; } else { line++; } } if ( foundFunctionDeclaration && ! foundClassDeclaration ) { indentsForNextStatement += DEFAULT_INDENT_LEVEL; } QString hintCode; if ( hintType == FunctionReturnHint ) { hintCode = "returns = " + typeCode; } else if ( hintType == LocalVariableHint ) { hintCode = "l_" + declarationIdentifier + " = " + typeCode; } qCDebug(KDEV_PYTHON_CODEGEN) << "Hint code: " << hintCode; hintCode.prepend(QString(indentsForNextStatement, ' ')); newCode.append(hintCode); for ( int i = 0; i < newCode.length(); i++ ) { m_code.insert(line + i, newCode.at(i)); } // We safely insert any import declaration at the top foreach ( const QString &moduleName, modules ) { bool importExists = false; foreach (const QString &line, m_code) { if ( ! line.startsWith("import") && ! line.startsWith("from") && ! line.isEmpty() ) { break; } // In both import ... and from ... import ..., the second part is what we want if ( line.section(' ', 1, 1, QString::SectionSkipEmpty) == moduleName.trimmed() ) { importExists = true; } } if ( ! importExists ) { m_code.prepend("import " + moduleName.trimmed()); } }