[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-10-31 23:57:36
Message-ID: 1193875056.004977.15539.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 731547 by zwabel:

Preprocess all text used for completion using the stored macros.
This results in better argument-matching and argument-hints for functions renamed \
using #define.



 M  +81 -14    codecompletioncontext.cpp  
 M  +3 -2      codecompletioncontext.h  


--- trunk/KDE/kdevelop/languages/cpp/codecompletioncontext.cpp #731546:731547
@@ -28,12 +28,26 @@
 #include "cppduchain/typeutils.h"
 #include "cppduchain/overloadresolution.h"
 #include "cppduchain/viablefunctions.h"
+#include "cppduchain/environmentmanager.h"
 #include "cpptypes.h"
 #include "safetycounter.h"
 #include "cpplanguagesupport.h"
+#include "parser/rpp/pp-engine.h"
+#include "parser/rpp/preprocessor.h"
+#include "parser/rpp/pp-environment.h"
+#include "parser/rpp/pp-macro.h"
+#include "parser/problem.h"
 
 #define LOCKDUCHAIN     DUChainReadLocker lock(DUChain::lock())
 
+//#define DEBUG
+
+#ifdef DEBUG
+#define ifDebug(x) x
+#else
+#define ifDebug(x)
+#endif
+
 using namespace Cpp;
 using namespace KDevelop;
 
@@ -54,6 +68,51 @@
 
 typedef PushValue<int> IntPusher;
 
+/**
+ * Preprocess the given string using the macros from given EnvironmentFile up to the \
given line + * If line is -1, all macros are respected.
+ * This is a quite slow operation, because thousands of macros need to be shuffled \
around. + * 
+ * @todo maybe implement a version of rpp::Environment that directly works on \
EnvironmentFile, + * without needing to copy all macros.
+ * */
+QString preprocess( const QString& text, const Cpp::EnvironmentFilePointer& file, \
int line ) { +
+  rpp::Preprocessor preprocessor;
+  rpp::pp pp(&preprocessor);
+
+  {
+    LOCKDUCHAIN;
+/*    kDebug() << "defined macros: " << file->definedMacros().size();*/
+    //Copy in all macros from the file
+    for( MacroSet::Macros::const_iterator it = \
file->definedMacros().macros().begin(); it != file->definedMacros().macros().end(); \
++it ) { +      if( line == -1 || line > (*it).sourceLine || !(file->url().equals( \
KUrl((*it).file) ) ) ) { +        pp.environment()->setMacro( new rpp::pp_macro( *it \
) ); +/*        kDebug() << "adding macro " << (*it).name.str();*/
+      } else {
+/*        kDebug() << "leaving macro " << (*it).name.str();*/
+      }
+    }
+/*    kDebug() << "used macros: " << file->usedMacros().size();*/
+    for( MacroSet::Macros::const_iterator it = file->usedMacros().macros().begin(); \
it != file->usedMacros().macros().end(); ++it ) { +      if( line == -1 || line > \
(*it).sourceLine || !(file->url().equals( KUrl((*it).file) ) ) ) { +        \
pp.environment()->setMacro( new rpp::pp_macro( *it ) ); +/*        kDebug() << \
"adding macro " << (*it).name.str();*/ +      } else {
+/*        kDebug() << "leaving macro " << (*it).name.str();*/
+      }
+    }
+  }
+
+  kDebug() << "text before preprocessing: " << text;
+  QString ret = pp.processFile("anonymous", rpp::pp::Data, text);
+  kDebug() << "text after preprocessing: " << ret;
+  pp.environment()->cleanup();
+  
+  return ret;
+}
+
+///Extracts the last line from the given string
 QString extractLastLine(const QString& str) {
   int prevLineEnd = str.lastIndexOf('\n');
   if(prevLineEnd != -1)
@@ -72,7 +131,7 @@
 
 int completionRecursionDepth = 0;
 
-CodeCompletionContext::CodeCompletionContext(DUContextPointer context, const \
QString& text, int depth, const QStringList& knownArgumentExpressions ) : \
m_memberAccessOperation(NoMemberAccess), m_valid(true), m_text(text), m_depth(depth), \
m_knownArgumentExpressions(knownArgumentExpressions), m_duContext(context), \
m_contextType(Normal), m_parentContext(0) \
+CodeCompletionContext::CodeCompletionContext(DUContextPointer context, const \
QString& text, int depth, const QStringList& knownArgumentExpressions, int line ) : \
m_memberAccessOperation(NoMemberAccess), m_valid(true), m_text(text), m_depth(depth), \
m_knownArgumentExpressions(knownArgumentExpressions), m_duContext(context), \
m_contextType(Normal), m_parentContext(0)  {
   IntPusher( completionRecursionDepth, completionRecursionDepth+1 );
 
@@ -104,14 +163,14 @@
     return;
   }
 
-  //log( "non-processed text: " + m_text );
-  preprocessText();
+  ifDebug( log( "non-processed text: " + m_text ); )
+   preprocessText( line );
 
-  m_text = Utils::clearComments( m_text );
-  m_text = Utils::clearStrings( m_text );
-  m_text = Utils::stripFinalWhitespace( m_text );
+   m_text = Utils::clearComments( m_text );
+   m_text = Utils::clearStrings( m_text );
+   m_text = Utils::stripFinalWhitespace( m_text );
 
-  //log( "processed text: " + m_text );
+  ifDebug( log( "processed text: " + m_text ); )
 
   ///@todo template-parameters
 
@@ -189,11 +248,11 @@
   int start_expr = Utils::expressionAt( m_text, m_text.length() );
 
   m_expression = m_text.mid(start_expr).trimmed();
-
-  kDebug() << start_expr << " found expression: " << m_expression << " in text: " << \
m_text;  
   QString expressionPrefix = Utils::stripFinalWhitespace( m_text.left(start_expr) );
 
+  ifDebug( log( "expressionPrefix: " + expressionPrefix ); )
+    
   ///Handle recursive contexts(Example: "ret = function1(param1, function2(" )
   if( expressionPrefix.endsWith('(') || expressionPrefix.endsWith(',') ) {
     log( QString("Recursive function-call: Searching parent-context in \
\"%1\"").arg(expressionPrefix) ); @@ -202,6 +261,7 @@
     //Find out which argument-number this expression is, and compute the beginning \
of the parent function-call(parentContextLast)  QStringList otherArguments;
     int parentContextEnd = expressionPrefix.length();
+    
     Utils::skipFunctionArguments( expressionPrefix, otherArguments, parentContextEnd \
);  
     QString parentContextText = expressionPrefix.left(parentContextEnd);
@@ -235,12 +295,13 @@
     expr = expr.right( expr.length() - 5 );
   }
 
-  ExpressionParser expressionParser;
+  ExpressionParser expressionParser/*(false, true)*/;
 
-  kDebug() << "expression: " << expr;
+  ifDebug( kDebug() << "expression: " << expr; )
   
   if( !expr.trimmed().isEmpty() ) {
     m_expressionResult = expressionParser.evaluateType( expr.toUtf8(), m_duContext \
); +    ifDebug( kDebug() << "expression result: " << m_expressionResult.toString(); \
)  if( !m_expressionResult.isValid() ) {
       if( m_memberAccessOperation != StaticMemberChoose ) {
         log( QString("expression \"%1\" could not be evaluated").arg(expr) );
@@ -489,9 +550,15 @@
   return ret;
 }
 
-void CodeCompletionContext::preprocessText() {
-  ///@todo implement, preprocess m_text in m_duContext at m_position
-  ///All macros can be found in the context's EnvironmentFile, in definedMacros() \
together with usedMacros() +void CodeCompletionContext::preprocessText( int line ) {
+  
+  LOCKDUCHAIN;
+  
+  if( m_duContext ) {
+  m_text = preprocess( m_text, Cpp::EnvironmentFilePointer( \
dynamic_cast<Cpp::EnvironmentFile*>(m_duContext->topContext()->parsingEnvironmentFile().data()) \
), line ); +  }else{
+    kWarning() << "error: no ducontext";
+  }
 }
 
 CodeCompletionContext::MemberAccessOperation \
                CodeCompletionContext::memberAccessOperation() const {
--- trunk/KDE/kdevelop/languages/cpp/codecompletioncontext.h #731546:731547
@@ -82,8 +82,9 @@
        * @param text the text to analyze. It usually is the text in the range \
starting at the beginning of the context, and ending at the position where completion \
                should start
        * @warning The du-chain must be unlocked when this is called
        * @param knownArgumentExpressions has no effect when firstContext is set
+       * @param line Optional line that will be used to filter the macros
        * */
-      CodeCompletionContext(KDevelop::DUContextPointer context, const QString& text, \
int depth = 0, const QStringList& knownArgumentExpressions = QStringList() ); +      \
CodeCompletionContext(KDevelop::DUContextPointer context, const QString& text, int \
depth = 0, const QStringList& knownArgumentExpressions = QStringList(), int line = -1 \
);  ~CodeCompletionContext();
 
       ///@return whether this context is valid for code-completion
@@ -158,7 +159,7 @@
       ///Returns whether the end of m_text is a valid completion-position
       bool isValidPosition();
       ///Should preprocess the given text(replace macros with their body etc.)
-      void preprocessText();
+      void preprocessText( int line );
       void processIncludeDirective(QString line);
       void log( const QString& str ) const;
       ///Returns whether the given strings ends with an overloaded operator that can \
form a parent-context


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic