[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdevelop/languages/cpp
From: David Nolden <david.nolden.kde () art-master ! de>
Date: 2007-06-30 19:35:14
Message-ID: 1183232114.482309.17069.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 681914 by zwabel:
Use the completion-context system from the completion-model, make parts of it work. \
With current svn kdelibs the completion-widget stays empty though, due to new bugs in \
kate completion code. With -r680492 some content should be visible.
M +88 -69 codecompletioncontext.cpp
M +5 -1 codecompletioncontext.h
M +40 -9 cppcodecompletionmodel.cpp
M +17 -0 duchainbuilder/cppduchain.cpp
M +1 -0 duchainbuilder/cppduchain.h
M +1 -1 expressionparser/expressionparser.cpp
M +9 -0 stringhelpers.cpp
M +2 -0 stringhelpers.h
--- trunk/KDE/kdevelop/languages/cpp/codecompletioncontext.cpp #681913:681914
@@ -60,6 +60,11 @@
CodeCompletionContext::Function::Function( int _matchedArguments, const \
ViableFunction& _viable ) : matchedArguments(_matchedArguments), function(_viable) { \
}
+CodeCompletionContext::operator bool() const {
+ return m_valid;
+}
+
+
CodeCompletionContext::CodeCompletionContext(DUContext * context, const \
KTextEditor::Cursor& position, KTextEditor::View* view, bool firstContext, const \
QStringList& knownArgumentExpressions ) : m_memberAccessOperation(NoMemberAccess), \
m_valid(true), m_knownArgumentExpressions(knownArgumentExpressions), \
m_duContext(context), m_position(position), m_view(view), \
m_document(view->document()), m_contextType(Normal), m_parentContext(0) {
static int depth = 0;
@@ -67,7 +72,7 @@
IntPusher( depth, depth+1 );
if( depth > 10 ) {
- log( "too much recursion" );
+ log( "CodeCompletionContext::CodeCompletionContext: too much recursion" );
m_valid = false;
return;
}
@@ -78,10 +83,14 @@
return;
}
- KTextEditor::Range range(context->textRange().start(), position);
-
- m_text = m_document->text(context->textRange());
- m_textStartPosition = context->textRange().start();
+ KTextEditor::Range range;
+ {
+ LOCKDUCHAIN;
+ range = KTextEditor::Range(context->textRange().start(), position);
+
+ m_text = m_document->text(range);
+ m_textStartPosition = context->textRange().start();
+ }
//Now text is the range that ends with the statement we are analyzing
if( m_text.isEmpty() ) {
@@ -95,10 +104,12 @@
return;
}
+ log( "non-processed text: " + m_text );
preprocessText();
m_text = Utils::clearComments( m_text );
m_text = Utils::clearStrings( m_text );
+ m_text = Utils::stripFinalWhitespace( m_text );
//text = Utils::reduceWhiteSpace(text);
@@ -107,6 +118,12 @@
///@todo template-parameters
///First: find out what kind of completion we are dealing with
+
+ if( m_text.endsWith( ";" ) || m_text.endsWith("}") || m_text.endsWith("{") ) {
+ ///We're at the beginning of a new statement. General completion is valid.
+ return;
+ }
+
if( m_text.endsWith(".") ) {
m_memberAccessOperation = MemberAccess;
m_text = m_text.left( m_text.length()-1 );
@@ -260,78 +277,80 @@
}
break;
case FunctionCallAccess:
- {
- ///Generate a list of all found functions/operators, together with each a list \
of optional prefixed parameters + processFunctionCallAccess();
+ break;
+ }
+}
- ///All the variable argument-count management in the following code is done to \
treat global operator-functions equivalently to local ones. They take a first \
parameter. +void CodeCompletionContext::processFunctionCallAccess() {
+ ///Generate a list of all found functions/operators, together with each a list of \
optional prefixed parameters
-
- typedef QPair<OverloadResolver::ParameterList, Declaration*> \
DeclarationWithArgument; + ///All the variable argument-count management in the \
following code is done to treat global operator-functions equivalently to local ones. \
They take a first parameter.
- QList< DeclarationWithArgument > declarations; //Declarations are paired with \
the optional first argument for the declared functions
-
- if( m_contextType == BinaryOperatorFunctionCall ) {
- if( !m_expressionResult->instance ) {
- log( "tried to apply an operator to a non-instance" );
- m_valid = false;
- return;
+ typedef QPair<OverloadResolver::ParameterList, Declaration*> \
DeclarationWithArgument; +
+ QList< DeclarationWithArgument > declarations; //Declarations are paired with the \
optional first argument for the declared functions +
+ if( m_contextType == BinaryOperatorFunctionCall ) {
+
+ if( !m_expressionResult->instance ) {
+ log( "tried to apply an operator to a non-instance" );
+ m_valid = false;
+ return;
+ }
+
+ QualifiedIdentifier identifier( "operator"+m_operator );
+ LOCKDUCHAIN;
+ ///Search for member operators
+ AbstractType::Ptr real( TypeUtils::realType(m_expressionResult->type.data()) );
+ if( dynamic_cast<CppClassType*>( real.data() ) )
+ {
+ IdentifiedType* idType = dynamic_cast<IdentifiedType*>( real.data() );
+ if( idType ) {
+ DUContext* ctx = TypeUtils::getInternalContext( idType->declaration() );
+ if( ctx ) {
+ QList<Declaration*> decls = Cpp::findLocalDeclarations( ctx, identifier );
+ foreach( Declaration* decl, decls )
+ declarations << DeclarationWithArgument( \
OverloadResolver::ParameterList(), decl ); + } else {
+ log( "no internal context found" );
}
-
- QualifiedIdentifier identifier( "operator"+m_operator );
- LOCKDUCHAIN;
- ///Search for member operators
- AbstractType::Ptr real( TypeUtils::realType(m_expressionResult->type.data()) \
);
- if( dynamic_cast<CppClassType*>( real.data() ) )
- {
- IdentifiedType* idType = dynamic_cast<IdentifiedType*>( real.data() );
- if( idType ) {
- DUContext* ctx = TypeUtils::getInternalContext( idType->declaration() );
- if( ctx ) {
- QList<Declaration*> decls = Cpp::findLocalDeclarations( ctx, \
identifier );
- foreach( Declaration* decl, decls )
- 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_duContext->findDeclarations(identifier);
- foreach( Declaration* decl, decls ) {
- FunctionType* fun = dynamic_cast<FunctionType*>( \
decl->abstractType().data() );
- if( fun && fun->arguments().size() == 2 )
- declarations << DeclarationWithArgument( \
OverloadResolver::Parameter(m_expressionResult->type.data(), \
m_expressionResult->isLValue()), decl );
- }
} else {
- ///Simply take all the declarations that were found by the expression-parser
- foreach( Declaration* decl, m_expressionResult->allDeclarations )
- declarations << DeclarationWithArgument( \
OverloadResolver::ParameterList(), decl ); //Insert with argument-offset zero + \
log( "type is not identified" ); }
- if( declarations.isEmpty() ) {
- log( QString("no list of function-declarations was computed for expression \
\"%1\"").arg(m_expression) );
- return;
- }
+ }
+ ///Search for static global operators
+ QList<Declaration*> decls = m_duContext->findDeclarations(identifier);
+ foreach( Declaration* decl, decls ) {
+ FunctionType* fun = dynamic_cast<FunctionType*>( decl->abstractType().data() \
); + if( fun && fun->arguments().size() == 2 )
+ declarations << DeclarationWithArgument( \
OverloadResolver::Parameter(m_expressionResult->type.data(), \
m_expressionResult->isLValue()), decl ); + }
+ } else {
+ ///Simply take all the declarations that were found by the expression-parser
+ foreach( Declaration* decl, m_expressionResult->allDeclarations )
+ declarations << DeclarationWithArgument( OverloadResolver::ParameterList(), \
decl ); //Insert with argument-offset zero + }
+ if( declarations.isEmpty() ) {
+ log( QString("no list of function-declarations was computed for expression \
\"%1\"").arg(m_expression) ); + return;
+ }
- QMap<Declaration*, int> m_argumentCountMap; //Maps how many pre-defined \
arguments where given to which function
- foreach( const DeclarationWithArgument& decl, declarations )
- m_argumentCountMap[decl.second] = decl.first.parameters.size();
-
- OverloadResolver resolv( m_duContext );
- OverloadResolver::ParameterList knownParameters;
- foreach( ExpressionEvaluationResult::Ptr result, m_knownArgumentTypes )
- knownParameters.parameters << OverloadResolver::Parameter( \
result->type.data(), result->isLValue() );
-
- QList< ViableFunction > viableFunctions = resolv.resolveListPartial( \
knownParameters, declarations );
- foreach( const ViableFunction& function, viableFunctions ) {
- if( function.declaration() && function.declaration()->abstractType() ) {
- m_functions << Function( m_argumentCountMap[function.declaration()] + \
knownParameters.parameters.size(), function );
- }
- }
+ QMap<Declaration*, int> m_argumentCountMap; //Maps how many pre-defined arguments \
where given to which function + foreach( const DeclarationWithArgument& decl, \
declarations ) + m_argumentCountMap[decl.second] = decl.first.parameters.size();
+
+ OverloadResolver resolv( m_duContext );
+ OverloadResolver::ParameterList knownParameters;
+ foreach( ExpressionEvaluationResult::Ptr result, m_knownArgumentTypes )
+ knownParameters.parameters << OverloadResolver::Parameter( result->type.data(), \
result->isLValue() ); +
+ QList< ViableFunction > viableFunctions = resolv.resolveListPartial( \
knownParameters, declarations ); + foreach( const ViableFunction& function, \
viableFunctions ) { + if( function.declaration() && \
function.declaration()->abstractType() ) { + m_functions << Function( \
m_argumentCountMap[function.declaration()] + knownParameters.parameters.size(), \
function ); }
- break;
}
}
@@ -356,7 +375,7 @@
markedText = Utils::clearStrings(markedText,'$');
if( markedText[markedText.length()-1] == '$' ) {
- //We are within a comment
+ //We are within a comment or string
return false;
}
return true;
--- trunk/KDE/kdevelop/languages/cpp/codecompletioncontext.h #681913:681914
@@ -68,7 +68,9 @@
ArrowMemberAccess, ///klass->
StaticMemberChoose, /// Class::
MemberChoose, /// klass->ParentClass::
- FunctionCallAccess ///"function(". Will never appear is initial \
access-operation, but as parentContext() access-operation. + \
FunctionCallAccess, ///"function(". Will never appear is initial access-operation, \
but as parentContext() access-operation. + SignalAccess, ///All signals from \
MemberAccessContainer should be listed + SlotAccess ///All slots from \
MemberAccessContainer should be listed };
/**
* The first context created will never be a FunctionCallAccess
@@ -140,6 +142,8 @@
private:
///@return the extracted expression, without any access-operation
QString expression() const;
+
+ void processFunctionCallAccess();
///Returns whether the end of m_text is a valid completion-position
bool isValidPosition();
--- trunk/KDE/kdevelop/languages/cpp/cppcodecompletionmodel.cpp #681913:681914
@@ -25,6 +25,8 @@
#include <ktexteditor/view.h>
#include <ktexteditor/document.h>
+#include "duchainbuilder/cppduchain.h"
+
#include <declaration.h>
#include "cpptypes.h"
#include <classfunctiondeclaration.h>
@@ -33,6 +35,7 @@
#include <duchainlock.h>
#include <topducontext.h>
#include "dumpchain.h"
+#include "codecompletioncontext.h"
using namespace KTextEditor;
using namespace KDevelop;
@@ -53,14 +56,17 @@
KUrl url = view->document()->url();
if (TopDUContext* top = DUChain::self()->chainForDocument(url)) {
kDebug(9007) << "completion invoked for context " << top << endl;
- DUChainReadLocker lock(DUChain::lock());
- DUContext* thisContext = top->findContextAt(range.start());
+ DUContext* thisContext;
+ {
+ DUChainReadLocker lock(DUChain::lock());
+ thisContext = top->findContextAt(range.start());
- kDebug(9007) << "context is set to " << thisContext << endl;
- {
- kDebug( 9007 ) << "================== duchain for the context \
=======================" << endl;
- DumpChain dump;
- dump.dump(thisContext);
+ kDebug(9007) << "context is set to " << thisContext << endl;
+ {
+ kDebug( 9007 ) << "================== duchain for the context \
=======================" << endl; + DumpChain dump;
+ dump.dump(thisContext);
+ }
}
setContext(thisContext, range.start(), view);
@@ -262,9 +268,34 @@
{
m_context = context;
Q_ASSERT(m_context);
- ///@todo move expression-evaluation into another thread
+ //@todo move completion-context-building into another thread
- m_declarations = m_context->allDeclarations(position).values();
+ m_declarations.clear();
+
+ Cpp::CodeCompletionContext completionContext( context, position, view );
+
+ if( completionContext ) {
+ DUChainReadLocker lock(DUChain::lock());
+
+ if( completionContext.memberAccessContainer() && \
*completionContext.memberAccessContainer() ) { + IdentifiedType* idType = \
dynamic_cast<IdentifiedType*>(completionContext.memberAccessContainer()->type.data());
+ if( idType && idType->declaration() ) {
+ DUContext* ctx = TypeUtils::getInternalContext( idType->declaration() );
+ if( ctx ) {
+ m_declarations = Cpp::localDeclarations( ctx );
+ } else {
+ kDebug() << "Could not get internal context from declaration \"" << \
idType->declaration()->toString() << "\"" << endl; + }
+ } else {
+ kDebug() << "CppCodeCompletionModel::setContext: bad container-type" << \
endl; + }
+ } else {
+ m_declarations = m_context->allDeclarations(position).values();
+ kDebug() << "CppCodeCompletionModel::setContext: using all declarations \
visible: " << m_declarations.count() << endl; + }
+ } else {
+ kDebug() << "CppCodeCompletionModel::setContext: Invalid code-completion \
context" << endl; + }
}
#include "cppcodecompletionmodel.moc"
--- trunk/KDE/kdevelop/languages/cpp/duchainbuilder/cppduchain.cpp #681913:681914
@@ -44,4 +44,21 @@
return ret;
}
+KDEVCPPDUCHAINBUILDER_EXPORT QList<KDevelop::Declaration*> localDeclarations( \
KDevelop::DUContext* context ) { + QList<Declaration*> ret;
+ ret += context->localDeclarations();
+ if( !ret.isEmpty() )
+ return ret;
+
+ if( context->type() != DUContext::Class )
+ return ret;
+
+ ///@todo exclude overloaded functions
+ QList<DUContext*> bases = context->importedParentContexts();
+ for( QList<DUContext*>::const_iterator it = bases.begin(); it != bases.end(); ++it \
) { + ret += localDeclarations( *it );
+ }
+ return ret;
}
+
+}
--- trunk/KDE/kdevelop/languages/cpp/duchainbuilder/cppduchain.h #681913:681914
@@ -38,6 +38,7 @@
* Du-chain must be locked before.
* */
QList<KDevelop::Declaration*> findLocalDeclarations( KDevelop::DUContext* context, \
const KDevelop::QualifiedIdentifier& identifier ); +QList<KDevelop::Declaration*> \
localDeclarations( KDevelop::DUContext* context );
}
--- trunk/KDE/kdevelop/languages/cpp/expressionparser/expressionparser.cpp \
#681913:681914 @@ -127,7 +127,7 @@
if( ret->type )
return ret;
else
- return ExpressionEvaluationResult::Ptr();
+ return ExpressionEvaluationResult::Ptr(new ExpressionEvaluationResult);
}
ExpressionEvaluationResult::Ptr ExpressionParser::evaluateType( AST* ast, \
ParseSession* session, bool debug ) {
--- trunk/KDE/kdevelop/languages/cpp/stringhelpers.cpp #681913:681914
@@ -133,7 +133,16 @@
return ret;
}
+QString stripFinalWhitespace(QString str) {
+
+ for( int a = str.length() - 1; a >= 0; --a ) {
+ if( !str[a].isSpace() )
+ return str.left( a+1 );
+ }
+ return QString::null;
+}
+
QString clearStrings( QString str, QChar /*replacement*/ ) {
///@todo implement: Replace all strings with the given replacement-character
return str;
--- trunk/KDE/kdevelop/languages/cpp/stringhelpers.h #681913:681914
@@ -39,6 +39,8 @@
* */
QString reduceWhiteSpace(QString str);
+QString stripFinalWhitespace(QString str);
+
/**
* Skips in the string backwards over function-arguments, and stops at the right \
side of a "("
* @param skippedArguments Will contain all skipped arguments
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic