[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