mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-24 19:02:53 +00:00
205 lines
7.5 KiB
C++
205 lines
7.5 KiB
C++
/*
|
|
Copyright 2007 David Nolden <david.nolden.kdevelop@art-master.de>
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License version 2 as published by the Free Software Foundation.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "overloadresolutionhelper.h"
|
|
|
|
#include <kdebug.h>
|
|
|
|
#include <language/duchain/declaration.h>
|
|
#include <language/duchain/ducontext.h>
|
|
#include <language/duchain/types/identifiedtype.h>
|
|
|
|
#include <cpptypes.h>
|
|
|
|
#include "typeutils.h"
|
|
#include "viablefunctions.h"
|
|
#include "cppduchain.h"
|
|
#include "adlhelper.h"
|
|
|
|
using namespace KDevelop;
|
|
using namespace Cpp;
|
|
|
|
///@todo Decide whether this should be enabled or disabled (by performance considerations)
|
|
bool useADLForOperators = true;
|
|
|
|
OverloadResolutionFunction::OverloadResolutionFunction() : matchedArguments(0) {
|
|
}
|
|
|
|
OverloadResolutionFunction::OverloadResolutionFunction( int _matchedArguments, const ViableFunction& _viable ) : matchedArguments(_matchedArguments), function(_viable) {
|
|
}
|
|
|
|
OverloadResolutionHelper::OverloadResolutionHelper(const KDevelop::DUContextPointer& context, const KDevelop::TopDUContextPointer& topContext)
|
|
: m_context(context)
|
|
, m_topContext(topContext)
|
|
, m_isOperator(false)
|
|
, m_constness(OverloadResolver::Unknown)
|
|
{
|
|
}
|
|
|
|
void OverloadResolutionHelper::setFunctionNameForADL(const KDevelop::QualifiedIdentifier& identifierForADL)
|
|
{
|
|
m_identifierForADL = identifierForADL;
|
|
}
|
|
|
|
void OverloadResolutionHelper::setOperator( const OverloadResolver::Parameter& base )
|
|
{
|
|
m_baseType = base;
|
|
m_isOperator = true;
|
|
}
|
|
|
|
void OverloadResolutionHelper::setFunctions( const QList<Declaration*>& functions )
|
|
{
|
|
foreach( Declaration* decl, functions )
|
|
m_declarations << DeclarationWithArgument( OverloadResolver::ParameterList(), decl ); //Insert with argument-offset zero
|
|
}
|
|
|
|
void OverloadResolutionHelper::setKnownParameters( const OverloadResolver::ParameterList& parameters )
|
|
{
|
|
m_knownParameters = parameters;
|
|
}
|
|
|
|
void OverloadResolutionHelper::setConstness( OverloadResolver::Constness constness )
|
|
{
|
|
m_constness = constness;
|
|
}
|
|
|
|
void OverloadResolutionHelper::initializeResolver(OverloadResolver& resolv)
|
|
{
|
|
if( m_isOperator ) {
|
|
Q_ASSERT(!m_identifierForADL.isEmpty());
|
|
///Search for member operators
|
|
AbstractType::Ptr real( TypeUtils::realType(m_baseType.type, m_context->topContext()) );
|
|
if( dynamic_cast<CppClassType*>( real.unsafeData() ) )
|
|
{
|
|
IdentifiedType* idType = dynamic_cast<IdentifiedType*>( real.unsafeData() );
|
|
if( idType && idType->declaration(m_context->topContext()) ) {
|
|
DUContext* ctx = idType->declaration(m_context->topContext())->logicalInternalContext(m_context->topContext());
|
|
if( ctx ) {
|
|
QList<Declaration*> decls = Cpp::findLocalDeclarations( ctx, m_identifierForADL.first(), m_context->topContext() );
|
|
foreach( Declaration* decl, decls )
|
|
m_declarations << DeclarationWithArgument( OverloadResolver::ParameterList(), decl );
|
|
} else {
|
|
log( "no internal context found" );
|
|
}
|
|
} else {
|
|
log( "type is not identified" );
|
|
}
|
|
}
|
|
///Search for static global operators
|
|
QList<Declaration*> decls = m_context->findDeclarations(m_identifierForADL);
|
|
foreach( Declaration* decl, decls ) {
|
|
FunctionType::Ptr fun = decl->abstractType().cast<FunctionType>();
|
|
if( fun && (fun->arguments().size() == 1 || fun->arguments().size() == 2) )
|
|
m_declarations << DeclarationWithArgument( m_baseType, decl );
|
|
}
|
|
///If no global or class member operators found try ADL for namespaced operators
|
|
if (m_declarations.isEmpty() && useADLForOperators) {
|
|
|
|
OverloadResolver::ParameterList params;
|
|
params.parameters << m_baseType;
|
|
params.parameters += m_knownParameters.parameters;
|
|
|
|
foreach( Declaration* decl, resolv.computeADLCandidates( params, m_identifierForADL ) ) {
|
|
FunctionType::Ptr fun = decl->abstractType().cast<FunctionType>();
|
|
if( fun && (fun->arguments().size() == 1 || fun->arguments().size() == 2) )
|
|
m_declarations << DeclarationWithArgument( m_baseType, decl );
|
|
}
|
|
}
|
|
}else{
|
|
//m_declarations should already be set by setFunctions(..)
|
|
}
|
|
|
|
foreach( const DeclarationWithArgument& decl, m_declarations )
|
|
m_argumentCountMap[decl.second] = decl.first.parameters.size();
|
|
|
|
// log( "functions given to overload-resolution:" );
|
|
// foreach( const DeclarationWithArgument& declaration, m_declarations )
|
|
// log( declaration.second->toString() );
|
|
|
|
// log("parameters given to overload-resolution:");
|
|
// lock.unlock();
|
|
// foreach( const ExpressionEvaluationResult& result, m_knownArgumentTypes ) {
|
|
// log( result.toString() );
|
|
// }
|
|
// lock.lock();
|
|
}
|
|
|
|
QList<OverloadResolutionFunction> OverloadResolutionHelper::resolveToList(bool partial)
|
|
{
|
|
OverloadResolver resolv( m_context, m_topContext, m_constness );
|
|
|
|
QList< ViableFunction > viableFunctions;
|
|
|
|
viableFunctions = resolv.resolveListOffsetted( m_knownParameters, m_declarations, partial );
|
|
|
|
// also retrieve names by ADL if partial argument list (only used by code completion)
|
|
// and even in strict mode if normal lookup failed
|
|
if (partial || viableFunctions.empty() || !viableFunctions[0].isViable()) {
|
|
|
|
QList<Declaration*> adlDecls = resolv.computeADLCandidates( m_knownParameters, m_identifierForADL );
|
|
if (!adlDecls.empty()) {
|
|
QList< DeclarationWithArgument > adlDeclsWithArguments;
|
|
foreach(Declaration * decl, adlDecls) {
|
|
adlDeclsWithArguments << DeclarationWithArgument( OverloadResolver::ParameterList(), decl ); // see setFunctions
|
|
}
|
|
viableFunctions += resolv.resolveListOffsetted( m_knownParameters, adlDeclsWithArguments, partial );
|
|
}
|
|
}
|
|
|
|
qSort( viableFunctions );
|
|
|
|
QList<OverloadResolutionFunction> ret;
|
|
|
|
foreach( const ViableFunction& function, viableFunctions )
|
|
{
|
|
if( function.declaration() && function.declaration()->abstractType() )
|
|
ret << OverloadResolutionFunction( m_argumentCountMap[function.declaration().data()] + m_knownParameters.parameters.size(), function );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
ViableFunction OverloadResolutionHelper::resolve(bool forceInstance)
|
|
{
|
|
OverloadResolver resolv( m_context, m_topContext, m_constness, forceInstance );
|
|
|
|
initializeResolver(resolv);
|
|
|
|
ViableFunction ret = resolv.resolveListViable( m_knownParameters, m_declarations );
|
|
|
|
// also retrieve names by ADL if partial argument list (only used by code completion)
|
|
// and even in strict mode if normal lookup failed
|
|
if (!ret.isViable()) {
|
|
QList<Declaration*> adlDecls = resolv.computeADLCandidates( m_knownParameters, m_identifierForADL );
|
|
if (!adlDecls.empty()) {
|
|
QList< DeclarationWithArgument > adlDeclsWithArguments;
|
|
foreach(Declaration * decl, adlDecls)
|
|
adlDeclsWithArguments << DeclarationWithArgument( OverloadResolver::ParameterList(), decl ); // see setFunctions
|
|
ret = resolv.resolveListViable( m_knownParameters, adlDeclsWithArguments );
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
void OverloadResolutionHelper::log(const QString& str) const
|
|
{
|
|
kDebug(9007) << "OverloadResolutionHelper: " << str;
|
|
}
|
|
|
|
|