Ticket #34545: context.cpp

File context.cpp, 83.7 KB (added by dragan.glumac@…, 12 years ago)
Line 
1/*
2   Copyright 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
3
4   This library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Library General Public
6   License version 2 as published by the Free Software Foundation.
7
8   This library is distributed in the hope that it will be useful,
9   but WITHOUT ANY WARRANTY; without even the implied warranty of
10   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11   Library General Public License for more details.
12
13   You should have received a copy of the GNU Library General Public License
14   along with this library; see the file COPYING.LIB.  If not, write to
15   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16   Boston, MA 02110-1301, USA.
17*/
18
19#include "context.h"
20#include <ktexteditor/view.h>
21#include <ktexteditor/document.h>
22#include <klocalizedstring.h>
23
24#include <iterator>
25
26#include <interfaces/idocumentcontroller.h>
27
28#include <language/interfaces/ilanguagesupport.h>
29#include <language/duchain/ducontext.h>
30#include <language/duchain/duchain.h>
31#include <language/duchain/duchainutils.h>
32#include <language/duchain/namespacealiasdeclaration.h>
33#include <language/duchain/classfunctiondeclaration.h>
34#include <language/duchain/functiondefinition.h>
35#include <language/duchain/duchainlock.h>
36#include <language/duchain/stringhelpers.h>
37#include <language/duchain/safetycounter.h>
38#include <language/interfaces/iproblem.h>
39#include <util/pushvalue.h>
40
41#include "../cppduchain/cppduchain.h"
42#include "../cppduchain/typeutils.h"
43#include "../cppduchain/overloadresolution.h"
44#include "../cppduchain/viablefunctions.h"
45#include "../cppduchain/environmentmanager.h"
46#include "../cppduchain/cpptypes.h"
47#include "../cppduchain/templatedeclaration.h"
48#include "../cpplanguagesupport.h"
49#include "../cpputils.h"
50#include "../cppduchain/environmentmanager.h"
51#include "../cppduchain/cppduchain.h"
52
53#include "cppdebughelper.h"
54#include "missingincludeitem.h"
55#include "implementationhelperitem.h"
56#include <qtfunctiondeclaration.h>
57#include "missingincludemodel.h"
58#include <templateparameterdeclaration.h>
59#include <language/duchain/classdeclaration.h>
60#include "qpropertydeclaration.h"
61#include "model.h"
62
63// #define ifDebug(x) x
64
65#define LOCKDUCHAIN     DUChainReadLocker lock(DUChain::lock())
66#include <cpputils.h>
67#include <interfaces/ilanguage.h>
68#include <interfaces/foregroundlock.h>
69
70///Created statically as this object must be a child of the main thread
71CppUtils::ReplaceCurrentAccess accessReplacer;
72
73///If this is enabled, no chain of useless argument-hints for binary operators is created.
74const bool NO_MULTIPLE_BINARY_OPERATORS = true;
75///Whether only items that are allowed to be accessed should be shown
76const bool DO_ACCESS_FILTERING = true;
77///Lines of text to keep for processing each context
78const int CONTEXT_LINES = 20;
79///Maximum number of parent contexts
80const int MAX_DEPTH = 10;
81
82/**
83 * ACCESS_STRINGS are used to determine the special properties of the context.
84 * Any alphanum_ word not appearing in ACCESS_STRINGS will be considered an expression.
85 * Expressions that fail evaluation invalidate their context and have no completions.
86 * Don't list a keyword in ACCESS_STRINGS if:
87 * * it should invalidate the context, ie ("break", "continue").
88 * * it should invalidate parent-only contexts, ie "if" will correctly invalidate a function ctxt
89 * Do list a keyword in ACCESS_STRINGS if:
90 * * it can be used to limit valid completions (see m_onlyShow, SHOW_TYPES_ACCESS_STRINGS)
91 * * if it should be ignored (ie, "else", "throw")
92 * * if it should be passed to a parent context for special processing (ie, "return", "(")
93 * UNARY_OPERATORS are not ACCESS_STRINGS, but are stripped away after counting ptr depth
94 **/
95const QSet<QString> BINARY_ARITHMETIC_OPERATORS = QString("+ - * / % ^ & | < >").split(' ').toSet();
96const QSet<QString> ARITHMETIC_COMPARISON_OPERATORS = QString("!= <= >= < >").split(' ').toSet();
97//technically ".", "->", ".*", "->*", "::" are also binary operators, but they're handled differently
98const QSet<QString> BINARY_OPERATORS =
99      QString("+= -= *= /= %= ^= &= |= ~= << >> >>= <<= == && || [ =").split(' ').toSet() +
100      BINARY_ARITHMETIC_OPERATORS + ARITHMETIC_COMPARISON_OPERATORS;
101//These will be skipped over to find parent contexts
102const QSet<QString> UNARY_OPERATORS = QString("++ -- ! ~ + - & *").split(' ').toSet();
103const QSet<QString> KEYWORD_ACCESS_STRINGS = QString("const_cast< static_cast< dynamic_cast< reinterpret_cast< const typedef public public: protected protected: private private: virtual return else throw emit Q_EMIT case delete delete[] new friend class").split(' ').toSet();
104//When these appear as access strings, only show types
105const QSet<QString> SHOW_TYPES_ACCESS_STRINGS = QString("const_cast< static_cast< dynamic_cast< reinterpret_cast< const typedef public protected private virtual new friend class").split(' ').toSet();
106//A parent context is created for these access strings
107//TODO: delete, case and possibly also xxx_cast< should open a parent context and get specialized handling
108const QSet<QString> PARENT_ACCESS_STRINGS = BINARY_OPERATORS + QString("< , ( : return case").split(' ').toSet();
109//TODO: support ".*" and "->*" as MEMBER_ACCESS_STRINGS
110const QSet<QString> MEMBER_ACCESS_STRINGS = QString(". -> ::").split(' ').toSet();
111const QSet<QString> ACCESS_STRINGS = KEYWORD_ACCESS_STRINGS + PARENT_ACCESS_STRINGS + MEMBER_ACCESS_STRINGS;
112
113///Pass these to getEndingFromSet in order to specify longest valid match for above sets
114const int ACCESS_STR_MATCH = 17; //reinterpret_cast<
115const int MEMBER_ACCESS_STR_MATCH = 2; //::
116const int PARENT_ACCESS_STR_MATCH = 6; //return
117const int BINARY_OPERATOR_MATCH = 3; //>>=
118const int UNARY_OPERATOR_MATCH = 2; //++
119
120//Whether identifiers starting with "__" or "_Uppercase" and that are not declared in the current file should be excluded from the code completion
121const bool excludeReservedIdentifiers = true;
122
123using namespace KDevelop;
124
125namespace Cpp {
126
127typedef QPair<Declaration*, int> DeclarationDepthPair;
128
129IndexedType switchExpressionType(DUContextPointer caseContext)
130{
131#ifndef TEST_COMPLETION
132  //Test thread has DUChain locked
133  ENSURE_CHAIN_NOT_LOCKED;
134#endif
135  ForegroundLock foregroundLock;
136  LOCKDUCHAIN;
137  if (!caseContext)
138    return IndexedType();
139  DUContext* switchContext = 0;
140  if (caseContext->importedParentContexts().size() == 1)
141    switchContext = caseContext->importedParentContexts().first().context(caseContext->topContext());
142  if (!switchContext)
143    return IndexedType();
144  QString switchExpression = switchContext->createRangeMoving()->text();
145  ExpressionParser expressionParser;
146  return expressionParser.evaluateType(switchExpression.toUtf8(), DUContextPointer(switchContext)).type;
147}
148
149//Search for a copy-constructor within class
150//*DUChain must be locked*
151bool hasCopyConstructor(CppClassType::Ptr classType, TopDUContext* topContext)
152{
153  if(!classType)
154    return false;
155  Declaration* decl = classType->declaration(topContext);
156  if(!decl)
157    return false;
158  DUContext* ctx = decl->internalContext();
159  if(!ctx)
160    return false;
161
162  AbstractType::Ptr constClassType = classType->indexed().abstractType();
163  constClassType->setModifiers(AbstractType::ConstModifier);
164  ReferenceType::Ptr argumentType(new ReferenceType);
165  argumentType->setBaseType(constClassType);
166
167  QList<Declaration*> constructors = ctx->findLocalDeclarations(decl->identifier());
168  foreach(Declaration* constructor, constructors) {
169    FunctionType::Ptr funType = constructor->type<FunctionType>();
170    if(funType && !funType->returnType() && funType->arguments().size() == 1) {
171      if(funType->arguments()[0]->equals(argumentType.constData()))
172        return true;
173    }
174  }
175
176  return false;
177}
178
179///@todo move these together with those from expressionvisitor into an own file, or make them unnecessary
180QList<Declaration*> declIdsToDeclPtrs( const QList<DeclarationId>& decls, uint count, TopDUContext* top ) {
181
182  QList<Declaration*> ret;
183  for(uint a = 0; a < count; ++a) {
184    Declaration* d = decls[a].getDeclaration(top);
185    if(d)
186      ret << d;
187  }
188
189  return ret;
190}
191
192bool isLegalIdentifier( const QChar &theChar ) {
193  return theChar.isLetterOrNumber() || theChar == '_';
194}
195
196///Gets the longest str from @param list which matches the ending of @param str
197QString getEndingFromSet( const QString &str, const QSet<QString> &set, int maxMatchLen) {
198  QString end;
199  for ( int i = qMin(str.length(), maxMatchLen); i > 0; --i ) {
200    end = str.right( i );
201    if ( i + i < str.length() &&
202         isLegalIdentifier( end[0] ) &&
203         isLegalIdentifier( str[str.length()-i-1] ) )
204      continue; //don't match ie, "varnamedelete[]"
205
206    if ( set.contains( end ) )
207      return end;
208  }
209
210  return QString(); 
211}
212
213QString getEndFunctionOperator( const QString &str ) {
214  QString ret = getEndingFromSet( str, BINARY_OPERATORS, BINARY_OPERATOR_MATCH );
215  return ret == "[" ? "[]" : str;
216}
217
218//Gets rid of uneeded whitespace following a legal identifier
219//"int i = " into "int i=" or "delete [ ] " into "delete[]"
220void compressEndingWhitespace( QString &str ) {
221  for (int i = str.length() - 1; i >= 0; --i) {
222    if ( isLegalIdentifier( str[i] ) )
223      return;
224    if ( str[i].isSpace() )
225      str.remove(i, 1);
226  }
227}
228
229QString whitespaceFree(const QString &orig)
230{
231  QString ret = orig;
232  for (int i = 0; i < ret.length(); ++i) {
233    if ( ret[i].isSpace() )
234      ret.remove(i, 1);
235  }
236  return ret;
237}
238
239bool isSignal( const QString &str )
240{
241  return str == "SIGNAL" || str == "Q_SIGNAL";
242}
243bool isSlot( const QString &str )
244{
245  return str == "SLOT" || str == "Q_SLOT";
246}
247
248QString lastNLines( const QString& str, int n ) {
249  int curNewLine = str.lastIndexOf( '\n' );
250  int nthLine = curNewLine;
251
252  for ( int i = 0; i < n; ++i )
253  {
254    if ( curNewLine == -1 )
255      break;
256    else
257      nthLine = curNewLine;
258
259    curNewLine = str.lastIndexOf( '\n', curNewLine - 1 );
260  }
261
262  //return the position after the newline, or whole str if no newline
263  return str.mid( nthLine + 1 );
264}
265
266bool skipToOpening( const QString& text, int &index)
267{
268  QChar closing = text[ index ];
269  QChar opening;
270  if ( closing == ')' )
271    opening = '(';
272  else if ( closing == '>' )
273    opening = '<';
274  else if ( closing == ']' )
275    opening = '[';
276
277  int count = 0;
278  int start = index;
279  while ( index >= 0 ) {
280    QChar ch = text[ index ];
281    --index;
282
283    if ( ch == opening )
284      ++count;
285    else if ( ch == closing )
286      --count;
287
288    if ( count == 0 )
289      return true;
290  }
291
292  index = start;
293  return false;
294}
295
296/**
297 * This function should search backwards in \p _text from \p index and return
298 * the index where the expression begins (if there is one)
299 * An expression is any legal identifier + member accesses + complete brackets
300 * Examples (expression begins at "|"):
301 * n = |(x + y)
302 * n = |x(y, z)
303 * n = x(|y
304 * n = |x()->y[].x<>::
305 * n = |x("whatever", ++y, x - u)
306 * Notes: Doesn't know about keywords
307**/
308int expressionBefore( const QString& _text, int index )
309{
310  QString text = KDevelop::clearStrings( _text );
311  bool lastWasIdentifier = false;
312
313  --index;
314
315  while ( index >= 0 )
316  {
317    while ( index >= 0 && text[ index ].isSpace() )
318      --index;
319
320    if ( index < 0 )
321      break;
322
323    QChar ch = text[ index ];
324    QString memberAccess = getEndingFromSet( text.left ( index + 1 ),
325                                             MEMBER_ACCESS_STRINGS,
326                                             MEMBER_ACCESS_STR_MATCH );
327    if ( !memberAccess.isEmpty() )
328    {
329      index -= memberAccess.length();
330      lastWasIdentifier = false;
331    }
332    else if ( !lastWasIdentifier && isLegalIdentifier( ch ) )
333    {
334      while ( index >= 0 && isLegalIdentifier( text[ index ] ) )
335        --index;
336      lastWasIdentifier = true;
337    }
338    else if ( !lastWasIdentifier && ( ch == ')' || ch == '>' || ch == ']' ) )
339    {
340      if ( skipToOpening ( text, index ) )
341        lastWasIdentifier = false;
342      else
343        break;
344    }
345    else
346      break;
347  }
348
349  ++index;
350
351  while ( index < text.length() && text[ index ].isSpace() )
352    ++index;
353
354  return index;
355}
356
357QString getUnaryOperator(const QString &context)
358{
359  QString unOp = getEndingFromSet( context, UNARY_OPERATORS, UNARY_OPERATOR_MATCH );
360  QString binOp = getEndingFromSet( context, BINARY_OPERATORS, BINARY_OPERATOR_MATCH );
361  if (!binOp.isEmpty()) {
362    if (binOp == unOp) {
363      int exprStart = expressionBefore(context, context.length() - binOp.length());
364      QString exp = context.mid(exprStart, context.length() - exprStart - binOp.length()).trimmed();
365      if ( !exp.isEmpty() && !KEYWORD_ACCESS_STRINGS.contains(exp) )
366        return QString();
367    }
368    else if (binOp.contains(unOp)) //ie "&&"
369      return QString();
370  }
371  return unOp;
372}
373
374CodeCompletionContext::
375CodeCompletionContext( KDevelop::DUContextPointer context, const QString& text,
376                       const QString& followingText, const KDevelop::CursorInRevision& position,
377                       int depth, const QStringList& knownArgumentExpressions, int line )
378  : KDevelop::CodeCompletionContext( context, text, position, depth ),
379    m_accessType( NoMemberAccess ),
380    m_knownArgumentExpressions( knownArgumentExpressions ),
381    m_isConstructorCompletion( false ),
382    m_pointerConversionsBeforeMatching( 0 ),
383    m_onlyShow( ShowAll ),
384    m_expressionIsTypePrefix( false ),
385    m_doAccessFiltering( DO_ACCESS_FILTERING )
386{
387#ifndef TEST_COMPLETION
388  MissingIncludeCompletionModel::self().stop();
389#endif
390  if ( doIncludeCompletion() )
391    return;
392  //We'll have to get a few expressionResults and do other DUChain processing during construction
393  //so lock the DUChain here
394  LOCKDUCHAIN;
395
396  if( !m_duContext || depth > MAX_DEPTH || !isValidPosition() ) {
397    m_valid = false;
398    return;
399  }
400
401  m_followingText = followingText.trimmed();
402
403  if( depth == 0 )
404    preprocessText( line );
405  m_text = lastNLines( m_text, CONTEXT_LINES );
406  compressEndingWhitespace( m_text );
407
408  if( doConstructorCompletion() )
409    return;
410
411  skipUnaryOperators( m_text, m_pointerConversionsBeforeMatching );
412
413  QString accessStr = getEndingFromSet( m_text, ACCESS_STRINGS, ACCESS_STR_MATCH );
414  m_accessType = findAccessType( accessStr );
415  if ( m_depth > 0 || !PARENT_ACCESS_STRINGS.contains( accessStr ) )
416    m_text.chop( accessStr.length() );
417
418  QString expressionPrefix;
419  findExpressionAndPrefix( m_expression, expressionPrefix, m_expressionIsTypePrefix );
420  skipUnaryOperators( expressionPrefix, m_pointerConversionsBeforeMatching );
421
422  m_localClass = findLocalClass();
423  m_parentContext = getParentContext( expressionPrefix );
424
425  if ( doSignalSlotCompletion() )
426    return;
427
428  m_onlyShow = findOnlyShow( accessStr );
429  m_expressionResult = evaluateExpression();
430
431  m_valid = testContextValidity(expressionPrefix, accessStr);
432  if (!m_valid)
433    return;
434
435  if ( m_accessType == TemplateAccess ||
436       m_accessType == FunctionCallAccess ||
437       m_accessType == BinaryOpFunctionCallAccess )
438  {
439    m_knownArgumentTypes = getKnownArgumentTypes();
440
441    if ( m_accessType == BinaryOpFunctionCallAccess )
442      m_operator = getEndFunctionOperator( accessStr );
443 
444    if( !m_expression.isEmpty() && !m_expressionResult.isValid() )
445      m_functionName = m_expression; //set m_functionName for Missing Include Completion
446  }
447
448  switch( m_accessType ) {
449    case ArrowMemberAccess:
450      processArrowMemberAccess();
451      //Falls through to processAllMemberAccesses, but only needs the missing include part TODO: refactor
452    case MemberChoose:
453    case StaticMemberChoose:
454    case MemberAccess:
455      processAllMemberAccesses();
456      break;
457    case BinaryOpFunctionCallAccess:
458    case FunctionCallAccess:
459      processFunctionCallAccess();
460      break;
461    default:
462      //Nothing to do for now
463    break;
464  }
465}
466
467void CodeCompletionContext::processAllMemberAccesses() {
468  AbstractType::Ptr type = m_expressionResult.type.abstractType();
469  if(!type)
470    return;
471
472  if(type.cast<PointerType>())
473    replaceCurrentAccess( ".", "->" );
474
475#ifndef TEST_COMPLETION // hmzzz ?? :) ///FIXME: manually test for these cases and get rid of comment to the left
476  DelayedType::Ptr delayed = type.cast<DelayedType>();
477  if( delayed && delayed->kind() == DelayedType::Unresolved ) {
478    eventuallyAddGroup(
479      i18n( "Not Included" ), 1000,
480      missingIncludeCompletionItems( m_expression, m_followingText + ": ",
481                                     m_expressionResult, m_duContext.data(), 0, true )
482    );
483  }
484#endif
485}
486
487void CodeCompletionContext::processArrowMemberAccess() {
488  //Dereference a pointer
489  AbstractType::Ptr containerType = m_expressionResult.type.abstractType();
490  PointerType::Ptr pnt = TypeUtils::realType( containerType, m_duContext->topContext() ).cast<PointerType>();
491  if( pnt ) {
492    ///@todo what about const in pointer?
493    m_expressionResult.type = pnt->baseType()->indexed();
494    m_expressionResult.isInstance = true;
495    return; // expression is a pointer
496  }
497
498  //Look for "->" operator
499  AbstractType::Ptr realContainer = TypeUtils::realType( containerType, m_duContext->topContext() );
500  IdentifiedType* idType = dynamic_cast<IdentifiedType*>( realContainer.unsafeData() );
501  if ( !idType ) {
502    m_valid = false;
503    return;
504  }
505
506  Declaration* idDecl = idType->declaration(m_duContext->topContext());
507  if( !idDecl || !idDecl->internalContext() ) {
508    m_valid = false;
509    return;
510  }
511
512  QList<Declaration*> operatorDeclarations =
513      Cpp::findLocalDeclarations( idDecl->internalContext(),
514                                  Identifier( "operator->" ),
515                                  m_duContext->topContext() );
516  if( operatorDeclarations.isEmpty() ) {
517    if( idDecl->internalContext()->type() == DUContext::Class )
518      replaceCurrentAccess( "->", "." );
519    m_valid = false;
520    return;
521  }
522
523  // TODO use Cpp::isAccessible on operator functions for more correctness?
524  foreach( Declaration* decl, operatorDeclarations )
525    m_expressionResult.allDeclarationsList().append( decl->id() );
526
527  bool declarationIsConst = ( containerType->modifiers() & AbstractType::ConstModifier ) ||
528                            ( idDecl->abstractType()->modifiers() & AbstractType::ConstModifier );
529  FunctionType::Ptr function;
530  foreach ( Declaration* decl, operatorDeclarations ) {
531    FunctionType::Ptr f2 = decl->abstractType().cast<FunctionType>();
532    const bool operatorIsConst = f2->modifiers() & AbstractType::ConstModifier;
533    if ( operatorIsConst == declarationIsConst ) {
534      // Best match
535      function = f2;
536      break;
537    } else if ( operatorIsConst && !function ) {
538      // Const result where non-const is ok, accept and keep looking
539      function = f2;
540    }
541  }
542
543  if ( !function ) {
544    m_valid = false;
545    return; //const declaration has no non-const "operator->"
546  }
547
548  m_expressionResult.type = function->returnType()->indexed();
549  m_expressionResult.isInstance = true;
550}
551
552bool CodeCompletionContext::testContextValidity(const QString &expressionPrefix, const QString &accessStr) const {
553  if( !m_expression.isEmpty() && !m_expressionResult.isValid() ) {
554    //StaticMemberChoose may be an access to a namespace, like "MyNamespace::".
555    //"MyNamespace" cannot be evaluated, still we can give some completions
556    //FunctionCallAccess & TemplateAccess can still get missing include completion
557    if( m_accessType != FunctionCallAccess &&
558        m_accessType != TemplateAccess &&
559        m_accessType != StaticMemberChoose )
560      return false;
561  }
562  //Special case for "class" access str, which should only have completions when it is "friend class ..."
563  if (accessStr == "class" && !expressionPrefix.endsWith("friend"))
564    return false;
565
566  switch ( m_accessType )
567  {
568    case NoMemberAccess:
569      return m_expression.isEmpty() || isImplementationHelperValid();
570    case BinaryOpFunctionCallAccess:
571      return m_expressionResult.isInstance;
572    case MemberAccess:
573    case MemberChoose:
574    case StaticMemberChoose:
575      return !m_expression.isEmpty();
576    default:
577      return true;
578  }
579}
580
581DUContextPointer CodeCompletionContext::findLocalClass() const {
582  Declaration* classDecl = Cpp::localClassFromCodeContext( m_duContext.data() );
583  return classDecl ? DUContextPointer( classDecl->internalContext() ) : DUContextPointer();
584}
585
586KDevelop::CodeCompletionContext::Ptr
587CodeCompletionContext::getParentContext( const QString &expressionPrefix ) const {
588  //this is essentially a poor-mans tokenizer, and we want to find out
589  //whether the last token is part of PARENT_ACCESS_STRINGS
590  //but we must take into account that longer versions exist in ACCESS_STRINGS,
591  //esp. for e.g. "parent:", here ":" would be a PARENT_ACCESS_STRINGS but
592  //it is actually not. So we first search in the long version and then
593  //double-check that it's actually a proper access string
594  QString access = getEndingFromSet( expressionPrefix, ACCESS_STRINGS, ACCESS_STR_MATCH );
595  if ( access.isEmpty() || !PARENT_ACCESS_STRINGS.contains(access) )
596    return KDevelop::CodeCompletionContext::Ptr();
597
598  QStringList previousArguments;
599  QString parentContextText;
600
601  if ( access == "," ) {
602    //Get arguments before current position
603    int parentContextEnd = expressionPrefix.length();
604    skipFunctionArguments( expressionPrefix, previousArguments, parentContextEnd );
605    parentContextText = expressionPrefix.left( parentContextEnd );
606  }
607  else
608    parentContextText = expressionPrefix;
609
610  if( m_depth == 0 || parentContextText != m_text )
611    return KDevelop::CodeCompletionContext::Ptr(
612        new CodeCompletionContext( m_duContext, parentContextText, QString(),
613                                   m_position, m_depth + 1, previousArguments ) );
614
615  return KDevelop::CodeCompletionContext::Ptr();
616}
617
618void CodeCompletionContext::skipUnaryOperators(QString &str, int &pointerConversions) const {
619  ///Eventually take preceding "*" and/or "&" operators and use them for pointer depth conversion of completion items
620  if ( str.endsWith("new") )
621    pointerConversions = 1;
622
623  QString unOp = getUnaryOperator( str );
624  while ( !unOp.isEmpty() ) {
625    unOp = getUnaryOperator( str );
626
627    if ( unOp == "&" )
628      ++pointerConversions;
629    else if ( unOp == "*" )
630      --pointerConversions;
631
632    str.chop(unOp.length());
633  }
634}
635
636bool CodeCompletionContext::doSignalSlotCompletion() {
637  if( m_depth > 0 || !parentContext() ||
638      parentContext()->accessType() != FunctionCallAccess)
639    return false;
640
641  //TODO: support "char* sig = SIGNAL(" properly
642  if( isSignal( parentContext()->m_expression ) || isSlot( parentContext()->m_expression ) ) {
643    m_onlyShow = isSlot(parentContext()->m_expression) ? ShowSlots : ShowSignals;
644    //If we are in "SIGNAL(" or "SLOT(" context, skip it
645    setParentContext(KDevelop::CodeCompletionContext::Ptr(parentContext()->parentContext()));
646  }
647
648  if( !parentContext() || !m_expression.isEmpty() ||
649      parentContext()->accessType() != FunctionCallAccess )
650    return false;
651
652  //Check if we're in a connect/disconnect function, and at what param
653  foreach( const Cpp::OverloadResolutionFunction &function, parentContext()->functions() )
654  {
655    DeclarationPointer decl = function.function.declaration();
656    if( !decl ||
657        ( decl->qualifiedIdentifier().toString() != "QObject::connect" &&
658          decl->qualifiedIdentifier().toString() != "QObject::disconnect") )
659      continue; //Not a connect/disconnect function
660
661    FunctionType::Ptr funType = decl->type<FunctionType>();
662    if( !funType || funType->arguments().size() <= function.matchedArguments ||
663        funType->arguments().size() < 3 )
664      continue; //Not a recognized overload
665
666    //this is a connect/disconnect, find if at SIGNAL or SLOT param
667    if( function.matchedArguments == 1 && parentContext()->m_knownArgumentTypes.size() >= 1 ) {
668      //currently at signal param
669      m_accessType = SignalAccess;
670    }
671    else if( funType->arguments()[function.matchedArguments] &&
672             funType->arguments()[function.matchedArguments]->toString() == "const char*" )
673    {
674      //currently at slot param
675      m_accessType = SlotAccess;
676
677      //get the corresponding signal's identifier and signature
678      if( parentContext()->m_knownArgumentExpressions.size() > 1 ) {
679        QString connectedSignal = parentContext()->m_knownArgumentExpressions[1];
680
681        int skipSignal = 0;
682        if( connectedSignal.startsWith( "SIGNAL(") )
683          skipSignal = 7;
684        if( connectedSignal.startsWith( "Q_SIGNAL(") )
685          skipSignal = 9;
686
687        if( skipSignal && connectedSignal.endsWith( ")" ) &&
688            connectedSignal.length() > skipSignal + 1 )
689        {
690          connectedSignal = connectedSignal.mid( skipSignal );
691          connectedSignal = connectedSignal.left( connectedSignal.length() - 1 );
692          //Now connectedSignal is something like myFunction(...), and we want the "...".
693          QPair<Identifier, QByteArray> signature = Cpp::qtFunctionSignature( connectedSignal.toUtf8() );
694          m_connectedSignalIdentifier = signature.first;
695          m_connectedSignalNormalizedSignature = signature.second;
696        }
697      }
698    }
699
700    if( m_accessType == SignalAccess || m_accessType == SlotAccess ) {
701      if( function.matchedArguments == 2 ) {
702        //The function that does not take the target-argument is being used
703        if( Declaration* klass = Cpp::localClassFromCodeContext( m_duContext.data() ) )
704          m_expressionResult.type = klass->indexedType();
705      }
706      else if( parentContext()->m_knownArgumentTypes.size() >=
707               function.matchedArguments && function.matchedArguments != 0 )
708      {
709        m_expressionResult = parentContext()->m_knownArgumentTypes[function.matchedArguments-1];
710        m_expressionResult.type = TypeUtils::targetType(TypeUtils::matchingClassPointer(funType->arguments()[function.matchedArguments-1], m_expressionResult.type.abstractType(), m_duContext->topContext()), m_duContext->topContext())->indexed();
711      }
712
713      return true;
714    }
715  }
716
717  return false;
718}
719
720ExpressionEvaluationResult CodeCompletionContext::evaluateExpression() const {
721  if( m_expression.isEmpty() )
722    return ExpressionEvaluationResult();
723
724  ExpressionParser expressionParser;
725
726  if( !m_expressionIsTypePrefix && m_accessType != NoMemberAccess )
727    return expressionParser.evaluateExpression( m_expression.toUtf8(), m_duContext );
728
729  ExpressionEvaluationResult res = expressionParser.evaluateType( m_expression.toUtf8(), m_duContext );
730  res.isInstance = true;
731  return res;
732}
733
734bool CodeCompletionContext::doConstructorCompletion() {
735  QString text = m_text.trimmed();
736
737  QStringList hadItems;
738
739  ifDebug( kDebug() << "text:" << text; )
740
741  //Jump over all initializers
742  while(!text.isEmpty() && text.endsWith(',')) {
743    text = text.left(text.length()-1).trimmed();
744    //Skip initializer expression
745    int start_expr = expressionBefore( text, text.length() );
746    QString skip = text.mid(start_expr, text.length() - start_expr);
747   
748    if(skip.contains('('))
749      hadItems << skip.left(skip.indexOf('(')).trimmed();
750   
751    text = text.left(start_expr).trimmed();
752  }
753 
754  if(!text.trimmed().endsWith(':'))
755    return false;
756
757  text = text.left(text.length()-1).trimmed();
758  //Now we have the declaration in text
759  ifDebug( kDebug() << "should be decl.:" << text; )
760  if(!text.endsWith(')'))
761    return false;
762 
763  int argumentsStart = text.length()-1;
764  QStringList arguments;
765  skipFunctionArguments(text, arguments, argumentsStart);
766  if(argumentsStart <= 0)
767    return false;
768 
769  int identifierStart = expressionBefore( text, argumentsStart-1 );
770  if(identifierStart < 0 || identifierStart == argumentsStart)
771    return false;
772 
773  m_text = QString();
774 
775  QualifiedIdentifier id(text.mid(identifierStart, argumentsStart-1-identifierStart));
776  if(id.isEmpty())
777    return false;
778  id = id.left(id.count()-1);
779 
780  DUContext* container = 0;
781 
782  if(!id.isEmpty()) {
783    //Find the class
784    QList< KDevelop::Declaration* > decls = m_duContext->findDeclarations(id);
785    if(decls.isEmpty()) {
786      ifDebug( kDebug() << "did not find class declaration for" << id.toString(); )
787      return false;
788    }
789    container = decls[0]->logicalInternalContext(m_duContext->topContext());
790  }else if(m_duContext->parentContext() && m_duContext->parentContext()->type() == DUContext::Class && m_duContext->parentContext()->owner()) {
791    container = m_duContext->parentContext();
792  }
793 
794  if(!container)
795    return false;
796 
797  m_onlyShow = ShowVariables;
798  m_isConstructorCompletion = true;
799  m_accessType = MemberAccess;
800  m_doAccessFiltering = false;
801 
802  QSet<QString> hadItemsSet = hadItems.toSet();
803 
804  QList<CompletionTreeItemPointer> items;
805 
806  int pos = 1000;
807  bool initializedNormalItems = false;
808 
809  //Pre-compute the items
810  foreach(Declaration* decl, container->localDeclarations(m_duContext->topContext())) {
811    ClassMemberDeclaration* classMem = dynamic_cast<ClassMemberDeclaration*>(decl);
812   
813    if(decl->kind() == Declaration::Instance && !decl->isFunctionDeclaration() && classMem && !classMem->isStatic()) {
814      if(!hadItemsSet.contains(decl->identifier().toString())) {
815        items << CompletionTreeItemPointer(new NormalDeclarationCompletionItem( DeclarationPointer(decl), KDevelop::CodeCompletionContext::Ptr(this), pos ));
816        ++pos;
817      }else{
818        initializedNormalItems = true;
819      }
820    }
821  }
822
823  if(!initializedNormalItems) {
824    //Only offer constructor initializations before variables were initialized
825    pos = 0;
826    foreach(const DUContext::Import& import, container->importedParentContexts()) {
827      DUContext* ctx = import.context(m_duContext->topContext());
828      if(ctx && ctx->type() == DUContext::Class && ctx->owner()) {
829          items.insert(pos, CompletionTreeItemPointer(new NormalDeclarationCompletionItem( DeclarationPointer(ctx->owner()), KDevelop::CodeCompletionContext::Ptr(this), pos )));
830          ++pos;
831      }
832    }
833  }
834 
835 
836  eventuallyAddGroup(i18n("Initialize"), 0, items);
837 
838  return true;
839  ///Step 1: Skip to the ':', to find the back of the function declaration. On the way, all expressions need to be constructor decls.
840}
841
842CodeCompletionContext::AccessType CodeCompletionContext::findAccessType( const QString &accessStr ) const {
843  if( accessStr == "." )
844    return MemberAccess;
845
846  if( accessStr == "->" )
847    return ArrowMemberAccess;
848
849  //TODO: add support for MemberChoose
850  if( accessStr == "::" )
851    return StaticMemberChoose;
852
853  if ( m_depth > 0 )
854  {
855    if( accessStr == "(" )
856      return FunctionCallAccess;
857
858    if (accessStr == "<" ) {
859      //We need to check here whether this really is a template access, or whether
860      //it is a "less than" operator, which is a BinaryOpFunctionCallAccess
861      int start_expr = expressionBefore( m_text, m_text.length()-1 );
862
863      QString expr = m_text.mid(start_expr, m_text.length() - start_expr - 1).trimmed();
864
865      ExpressionParser expressionParser;
866      Cpp::ExpressionEvaluationResult result =
867          expressionParser.evaluateExpression(expr.toUtf8(), m_duContext);
868      if( result.isValid() &&
869          ( !result.isInstance || result.type.type<FunctionType>() ) &&
870          !result.type.type<DelayedType>() )
871        return TemplateAccess;
872    }
873
874    if ( accessStr == "return" )
875      return ReturnAccess;
876
877    if ( accessStr == "case" )
878      return CaseAccess;
879
880    if( BINARY_OPERATORS.contains( accessStr ) )
881      return BinaryOpFunctionCallAccess;
882  }
883
884  return NoMemberAccess;
885}
886
887void CodeCompletionContext::
888findExpressionAndPrefix(QString& expression, QString& expressionPrefix, bool &isTypePrefix) const {
889  int start_expr;
890  start_expr = expressionBefore( m_text, m_text.length() );
891  expression = m_text.mid( start_expr ).trimmed();
892
893  if ( KEYWORD_ACCESS_STRINGS.contains( expression ) ) {
894    expression = QString();
895    start_expr = -1;
896  }
897
898  expressionPrefix = m_text.left(start_expr).trimmed();
899  compressEndingWhitespace( expressionPrefix );
900
901  if ( expressionPrefix.isEmpty() )
902    return;
903
904  ///handle "Type instance(" or "Type instance =". The "Type" part will be in the prefix
905  if( expressionPrefix.endsWith('>') || expressionPrefix.endsWith('*') ||
906      isLegalIdentifier( expressionPrefix[expressionPrefix.length()-1] ) ) {
907
908    int  ptrs = 0;
909    while ( expressionPrefix.endsWith( QString( "*" ).repeated( ptrs + 1 ) ) )
910      ++ptrs;
911    int newExpressionStart = expressionBefore(expressionPrefix, expressionPrefix.length() - ptrs);
912    QString newExpression = expressionPrefix.mid( newExpressionStart ).trimmed();
913
914    //Make sure it's not picking up something like "if (a < a > b)"
915    ExpressionParser expressionParser;
916    ExpressionEvaluationResult res = expressionParser.evaluateType( newExpression.toUtf8(), m_duContext );
917
918    //must use toString() comparison because sometimes isInstance is wrong (ie "var*", "new", "") TODO: fix
919    if ( res.isValid() && !res.isInstance && whitespaceFree( res.toString() ) == whitespaceFree( newExpression ) ) {
920      expressionPrefix = expressionPrefix.left( newExpressionStart );
921      compressEndingWhitespace( expressionPrefix );
922      expression = newExpression;
923      isTypePrefix = true;
924      return;
925    }
926  }
927
928  //Add reference and dereference operators to expression
929  QString op; 
930  while ( true ) {
931    op = getUnaryOperator(expressionPrefix);
932    if (op == "*" || op == "&") {
933      expression.prepend(op);
934      expressionPrefix.chop(op.length());
935    } else
936      break;
937  }
938}
939
940QList< ExpressionEvaluationResult > CodeCompletionContext::getKnownArgumentTypes() const {
941  ExpressionParser expressionParser;
942  QList< ExpressionEvaluationResult > expressionResults;
943  for( QStringList::const_iterator it = m_knownArgumentExpressions.constBegin();
944       it != m_knownArgumentExpressions.constEnd(); ++it ) {
945    expressionResults << expressionParser.evaluateExpression( (*it).toUtf8(), m_duContext );
946  }
947
948  return expressionResults;
949}
950
951CodeCompletionContext::OnlyShow CodeCompletionContext::findOnlyShow(const QString &accessStr) const {
952  //TODO: ShowSignals/Slots doesn't work at all outside of connect/disconnect,
953  //but should be used for ie "const char * x = SIGNAL("
954  //TODO: Should only show types for a SHOW_TYPES_ACCESS_STRINGS in expressionPrefix
955  //(at least for StaticMemberChoose)
956
957  //Either there's no expression, which means Global completion,
958  //or there is an expression, which means implementationhelperitems only
959  if ( m_accessType == NoMemberAccess && !m_expression.isEmpty() &&
960       isImplementationHelperValid() )
961    return ShowImplementationHelpers;
962
963  if( SHOW_TYPES_ACCESS_STRINGS.contains( accessStr ) )
964    return ShowTypes;
965
966  if ( parentContext() && parentContext()->accessType() == TemplateAccess )
967    return ShowTypes;
968
969  //Only ShowTypes in these DUContexts unless initializing a declaration
970  //ie, m_expressionIsTypePrefix == true
971  if (m_duContext->type() == DUContext::Class ||
972      m_duContext->type() == DUContext::Namespace ||
973      m_duContext->type() == DUContext::Global )
974  {
975    CodeCompletionContext* ctxt = parentContext();
976    while (ctxt && !ctxt->m_expressionIsTypePrefix)
977      ctxt = ctxt->parentContext();
978
979    if ( !ctxt && !m_expressionIsTypePrefix )
980      return ShowTypes;
981  }
982
983  return ShowAll;
984}
985
986QList< Cpp::ExpressionEvaluationResult > CodeCompletionContext::knownArgumentTypes() const {
987  return m_knownArgumentTypes;
988}
989
990bool CodeCompletionContext::isConstructorInitialization() {
991  return m_isConstructorCompletion;
992}
993
994void CodeCompletionContext::processFunctionCallAccess() {
995  ///Generate a list of all found functions/operators, together with each a list of optional prefixed parameters
996  ///All the variable argument-count management in the following code is done to treat global operator-functions equivalently to local ones. Those take an additional first argument.
997
998  OverloadResolutionHelper helper( m_duContext, TopDUContextPointer(m_duContext->topContext()) );
999
1000  if( m_accessType == BinaryOpFunctionCallAccess ) {
1001
1002    helper.setOperator(OverloadResolver::Parameter(m_expressionResult.type.abstractType(), m_expressionResult.isLValue()));
1003
1004    m_functionName = "operator"+m_operator;
1005   
1006  } else {
1007    ///Simply take all the declarations that were found by the expression-parser
1008
1009    helper.setFunctions(declIdsToDeclPtrs(m_expressionResult.allDeclarations, m_expressionResult.allDeclarationsSize(), m_duContext->topContext()));
1010
1011    if(m_expressionResult.allDeclarationsSize()) {
1012      Declaration* decl = m_expressionResult.allDeclarations[0].getDeclaration(m_duContext->topContext());
1013      if(decl)
1014        m_functionName = decl->identifier().toString();
1015    }
1016  }
1017
1018  if( m_accessType == BinaryOpFunctionCallAccess || m_expression == m_functionName )
1019    helper.setFunctionNameForADL( QualifiedIdentifier(m_functionName) );
1020 
1021  OverloadResolver::ParameterList knownParameters;
1022  foreach( const ExpressionEvaluationResult &result, m_knownArgumentTypes )
1023    knownParameters.parameters << OverloadResolver::Parameter( result.type.abstractType(), result.isLValue() );
1024
1025  helper.setKnownParameters(knownParameters);
1026
1027  m_matchingFunctionOverloads = helper.resolveToList(true);
1028
1029  if(m_accessType == BinaryOpFunctionCallAccess) {
1030    //Filter away all global binary operators that do not have the first argument matched
1031    QList< Function > oldFunctions = m_matchingFunctionOverloads;
1032    m_matchingFunctionOverloads.clear();
1033    foreach(const Function& f, oldFunctions) {
1034      if(f.matchedArguments == 1 && !f.function.isViable())
1035        continue;
1036      else
1037        m_matchingFunctionOverloads << f;
1038    }
1039  }
1040}
1041
1042bool CodeCompletionContext::doIncludeCompletion()
1043{
1044  QString line = lastNLines(m_text, 1).trimmed();
1045  if(!line.startsWith("#"))
1046    return false;
1047
1048  if(line.count('"') == 2 || line.endsWith('>'))
1049    return true; //We are behind a complete include-directive
1050
1051  int endOfInclude = CppUtils::findEndOfInclude(line);
1052  if(endOfInclude == -1)
1053    return true;
1054
1055  //Strip away #include
1056  line = line.mid(endOfInclude).trimmed();
1057 
1058  kDebug(9007) << "trimmed include line: " << line;
1059
1060  if(!line.startsWith('<') && !line.startsWith('"'))
1061    return true; //We are not behind the beginning of a path-specification
1062
1063  line = line.mid(1);
1064
1065  kDebug(9007) << "extract prefix from " << line;
1066  //Extract the prefix-path
1067  KUrl u(line);
1068
1069  QString prefixPath;
1070  if(line.contains('/')) {
1071    u.setFileName(QString());
1072    prefixPath = u.toLocalFile();
1073  }
1074  kDebug(9007) << "extracted prefix " << prefixPath;
1075
1076#ifndef TEST_COMPLETION
1077  bool local = line.startsWith('"');
1078  m_includeItems = CppUtils::allFilesInIncludePath(KUrl(m_duContext->url().str()), local, prefixPath);
1079#endif
1080
1081  m_accessType = IncludeListAccess;
1082
1083  return true;
1084}
1085
1086const CodeCompletionContext::FunctionList& CodeCompletionContext::functions() const {
1087  return m_matchingFunctionOverloads;
1088}
1089
1090QString CodeCompletionContext::functionName() const {
1091  return m_functionName;
1092}
1093
1094QList<Cpp::IncludeItem> CodeCompletionContext::includeItems() const {
1095  return m_includeItems;
1096}
1097
1098ExpressionEvaluationResult CodeCompletionContext::memberAccessContainer() const {
1099  return m_expressionResult;
1100}
1101
1102QSet<DUContext*> CodeCompletionContext::memberAccessContainers() const {
1103  QSet<DUContext*> ret;
1104
1105  if( m_accessType == StaticMemberChoose && m_duContext ) {
1106    //Locate all namespace-instances we will be completing from
1107    QList< Declaration* > decls = m_duContext->findDeclarations(QualifiedIdentifier(m_expression)); ///@todo respect position
1108
1109    // qlist does not provide convenient stable iterators
1110    // std::list<Declaration*> worklist(decls.begin(), decls.end());
1111    for (QList<Declaration*>::iterator it = decls.begin(); it != decls.end(); ++it) {
1112      Declaration * decl = *it;
1113      if((decl->kind() == Declaration::Namespace || dynamic_cast<ClassDeclaration*>(decl))  && decl->internalContext())
1114        ret.insert(decl->internalContext());
1115      else if (decl->kind() == Declaration::NamespaceAlias) {
1116        NamespaceAliasDeclaration * aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(decl);
1117        if (aliasDecl) {
1118          QList<Declaration*> importedDecls = m_duContext->findDeclarations(aliasDecl->importIdentifier()); ///@todo respect position
1119          std::copy(importedDecls.begin(), importedDecls.end(),
1120                    std::back_inserter(decls));
1121        }
1122      }
1123    }
1124  }
1125
1126  if(m_expressionResult.isValid() ) {
1127    AbstractType::Ptr expressionTarget = TypeUtils::targetType(m_expressionResult.type.abstractType(), m_duContext->topContext());
1128    const IdentifiedType* idType = dynamic_cast<const IdentifiedType*>( expressionTarget.unsafeData() );
1129      Declaration* idDecl = 0;
1130    if( idType && (idDecl = idType->declaration(m_duContext->topContext())) ) {
1131      DUContext* ctx = idDecl->logicalInternalContext(m_duContext->topContext());
1132      if( ctx ){
1133        if(ctx->type() != DUContext::Template) //Forward-declared template classes have a template-context assigned. Those should not be searched.
1134          ret.insert(ctx);
1135      }else {
1136        //Print some debug-output
1137        kDebug(9007) << "Could not get internal context from" << m_expressionResult.type.abstractType()->toString();
1138        kDebug(9007) << "Declaration" << idDecl->toString() << idDecl->isForwardDeclaration();
1139        if( Cpp::TemplateDeclaration* tempDeclaration = dynamic_cast<Cpp::TemplateDeclaration*>(idDecl) ) {
1140          if( tempDeclaration->instantiatedFrom() ) {
1141            kDebug(9007) << "instantiated from" << dynamic_cast<Declaration*>(tempDeclaration->instantiatedFrom())->toString() << dynamic_cast<Declaration*>(tempDeclaration->instantiatedFrom())->isForwardDeclaration();
1142            kDebug(9007) << "internal context" << dynamic_cast<Declaration*>(tempDeclaration->instantiatedFrom())->internalContext();
1143          }
1144        }
1145
1146      }
1147    }
1148  }
1149 
1150//   foreach(DUContext* context, ret) {
1151//     kDebug() << "member-access container:" << context->url().str() << context->range().textRange() << context->scopeIdentifier(true).toString();
1152//   }
1153
1154  return ret;
1155}
1156
1157KDevelop::IndexedType CodeCompletionContext::applyPointerConversionForMatching(KDevelop::IndexedType type, bool fromLValue) const {
1158  if(!m_duContext)
1159    return KDevelop::IndexedType();
1160 
1161  if(m_pointerConversionsBeforeMatching == 0)
1162    return type;
1163  AbstractType::Ptr t = type.abstractType();
1164  if(!t)
1165    return KDevelop::IndexedType();
1166
1167  //Can only take addresses of lvalues
1168  if(m_pointerConversionsBeforeMatching > 1 || (m_pointerConversionsBeforeMatching && !fromLValue))
1169    return IndexedType();
1170 
1171  if(m_pointerConversionsBeforeMatching > 0) {
1172    for(int a = 0; a < m_pointerConversionsBeforeMatching; ++a) {
1173     
1174      t = TypeUtils::increasePointerDepth(t);
1175      if(!t)
1176        return IndexedType();
1177    }
1178  }else{
1179    for(int a = m_pointerConversionsBeforeMatching; a < 0; ++a) {
1180      t = TypeUtils::decreasePointerDepth(t, m_duContext->topContext());
1181      if(!t)
1182        return IndexedType();
1183    }
1184  }
1185 
1186  return t->indexed();
1187}
1188
1189CodeCompletionContext::~CodeCompletionContext() {
1190}
1191
1192bool CodeCompletionContext::isValidPosition() {
1193  if( m_text.isEmpty() )
1194    return true;
1195  //If we are in a string or comment, we should not complete anything
1196  QString markedText = clearComments(m_text, '$');
1197  markedText = clearStrings(markedText,'$');
1198
1199  if( markedText[markedText.length()-1] == '$' ) {
1200    //We are within a comment or string
1201    kDebug(9007) << "code-completion position is invalid, marked text: \n\"" << markedText << "\"\n unmarked text:\n" << m_text << "\n";
1202    return false;
1203  }
1204  return true;
1205}
1206
1207
1208bool CodeCompletionContext::isImplementationHelperValid() const
1209{
1210  if (m_onlyShow == ShowVariables || m_isConstructorCompletion)
1211    return false;
1212  if (m_accessType != NoMemberAccess && m_accessType != StaticMemberChoose)
1213    return false;
1214
1215  LOCKDUCHAIN;
1216  if (!m_duContext)
1217    return false;
1218
1219  return ( !parentContext() && ( m_duContext->type() == DUContext::Namespace ||
1220                                 m_duContext->type() == DUContext::Global) );
1221}
1222
1223static TopDUContext* proxyContextForUrl(KUrl url)
1224{
1225  QList< ILanguage* > languages = ICore::self()->languageController()->languagesForUrl(url);
1226  foreach(ILanguage* language, languages)
1227  {
1228    if(language->languageSupport())
1229      return language->languageSupport()->standardContext(url, true);
1230  }
1231 
1232  return 0;
1233}
1234
1235void CodeCompletionContext::preprocessText( int line ) {
1236  QSet<IndexedString> disableMacros;
1237  disableMacros.insert(IndexedString("SIGNAL"));
1238  disableMacros.insert(IndexedString("SLOT"));
1239  disableMacros.insert(IndexedString("emit"));
1240  disableMacros.insert(IndexedString("Q_EMIT"));
1241  disableMacros.insert(IndexedString("Q_SIGNAL"));
1242  disableMacros.insert(IndexedString("Q_SLOT"));
1243
1244  // Use the proxy-context if possible, because that one contains most of the macros if existent
1245  TopDUContext* useTopContext = proxyContextForUrl(m_duContext->url().toUrl());
1246  if(!useTopContext)
1247    useTopContext = m_duContext->topContext();
1248
1249  m_text = preprocess( m_text, dynamic_cast<Cpp::EnvironmentFile*>(useTopContext->parsingEnvironmentFile().data()), line, disableMacros );
1250
1251  m_text = clearComments( m_text );
1252}
1253
1254CodeCompletionContext::AccessType CodeCompletionContext::accessType() const {
1255  return m_accessType;
1256}
1257
1258CodeCompletionContext* CodeCompletionContext::parentContext() const {
1259  return KSharedPtr<CodeCompletionContext>::staticCast(m_parentContext).data();
1260}
1261
1262void getOverridable(DUContext* base, DUContext* current, QMap< QPair<IndexedType, IndexedString>, KDevelop::CompletionTreeItemPointer >& overridable, CodeCompletionContext::Ptr completionContext, int depth = 0) {
1263  if(!current)
1264    return;
1265 
1266  foreach(Declaration* decl, current->localDeclarations()) {
1267    ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(decl);
1268    // one can only override the direct parent's ctor
1269    if(classFun && (classFun->isVirtual() || (depth == 0 && classFun->isConstructor()))) {
1270      QPair<IndexedType, IndexedString> key = qMakePair(classFun->indexedType(), classFun->identifier().identifier());
1271      if(base->owner()) {
1272        if(classFun->isConstructor() || classFun->isDestructor())
1273          key.second = base->owner()->identifier().identifier();
1274        if(classFun->isDestructor())
1275          key.second = IndexedString("~" + key.second.str());
1276      }
1277      if(!overridable.contains(key) && base->findLocalDeclarations(KDevelop::Identifier(key.second), CursorInRevision::invalid(), 0, key.first.abstractType(), KDevelop::DUContext::OnlyFunctions).isEmpty())
1278        overridable.insert(key, KDevelop::CompletionTreeItemPointer(new ImplementationHelperItem(ImplementationHelperItem::Override, DeclarationPointer(decl), completionContext, (classFun && classFun->isAbstract()) ? 1 : 2)));
1279    }
1280  }
1281
1282  foreach(const DUContext::Import &import, current->importedParentContexts())
1283    getOverridable(base, import.context(base->topContext()), overridable, completionContext, depth + 1);
1284}
1285
1286// #ifndef TEST_COMPLETION
1287
1288QList< KSharedPtr< KDevelop::CompletionTreeElement > > CodeCompletionContext::ungroupedElements() {
1289  return m_storedUngroupedItems;
1290}
1291
1292QList<CompletionTreeItemPointer> CodeCompletionContext::memberAccessCompletionItems( const bool& shouldAbort )
1293{
1294  QList<CompletionTreeItemPointer> items;
1295  LOCKDUCHAIN; if (!m_duContext) return items;
1296
1297  if( !memberAccessContainer().isValid() && m_accessType != StaticMemberChoose )
1298    return items;
1299
1300  bool typeIsConst = false;
1301  AbstractType::Ptr expressionTarget = TypeUtils::targetType(m_expressionResult.type.abstractType(), m_duContext->topContext());
1302  if (expressionTarget && (expressionTarget->modifiers() & AbstractType::ConstModifier))
1303    typeIsConst = true;
1304
1305  QSet<DUContext*> containers = memberAccessContainers();
1306  ifDebug( kDebug() << "got" << containers.size() << "member-access containers"; )
1307  if (containers.isEmpty())
1308  {
1309    ifDebug( kDebug() << "missing-include completion for" << m_expression << m_expressionResult.toString(); )
1310    eventuallyAddGroup(i18n("Not Included Container"), 700, missingIncludeCompletionItems(m_expression, QString(), m_expressionResult, m_duContext.data(), 0, true ));
1311  }
1312
1313  //Used to show only one namespace-declaration per namespace
1314  QSet<QualifiedIdentifier> hadNamespaceDeclarations;
1315
1316  foreach(DUContext* ctx, containers) {
1317    if (shouldAbort)
1318      return items;
1319    ifDebug( kDebug() << "container:" << ctx->scopeIdentifier(true).toString(); )
1320
1321    foreach( const DeclarationDepthPair& decl,
1322            Cpp::hideOverloadedDeclarations(
1323              ctx->allDeclarations(ctx->range().end, m_duContext->topContext(), false ),
1324              typeIsConst ) )
1325    {
1326      //If we have StaticMemberChoose, which means A::Bla, show only static members, except if we're within a class that derives from the container
1327      ClassMemberDeclaration* classMember = dynamic_cast<ClassMemberDeclaration*>(decl.first);
1328
1329      if(classMember && !filterDeclaration(classMember, ctx))
1330        continue;
1331      else if(!filterDeclaration(decl.first, ctx))
1332        continue;
1333
1334      if (accessType() == MemberAccess || accessType() == ArrowMemberAccess) {
1335        // Don't allow constructors to be accessed with . or ->
1336        if (ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(classMember))
1337          if (classFun->isConstructor())
1338            continue;
1339      }
1340
1341      if(decl.first->kind() == Declaration::Namespace) {
1342        QualifiedIdentifier id = decl.first->qualifiedIdentifier();
1343        if(hadNamespaceDeclarations.contains(id))
1344          continue;
1345
1346        hadNamespaceDeclarations.insert(id);
1347      }
1348
1349      if(accessType() != Cpp::CodeCompletionContext::StaticMemberChoose) {
1350        if(decl.first->kind() != Declaration::Instance && decl.first->kind() != Declaration::Alias)
1351          continue;
1352        if(decl.first->abstractType().cast<EnumeratorType>())
1353          continue; //Skip enumerators
1354      }else{
1355        ///@todo what NOT to show on static member choose? Actually we cannot hide all non-static functions, because of function-pointers
1356      }
1357
1358      if(!decl.first->identifier().isEmpty())
1359        items << CompletionTreeItemPointer( new NormalDeclarationCompletionItem( DeclarationPointer(decl.first), KDevelop::CodeCompletionContext::Ptr(this), decl.second ) );
1360    }
1361  }
1362
1363  return items;
1364}
1365
1366QList<CompletionTreeItemPointer> CodeCompletionContext::returnAccessCompletionItems()
1367{
1368  QList<CompletionTreeItemPointer> items;
1369  LOCKDUCHAIN; if (!m_duContext) return items;
1370
1371  DUContext* functionContext = m_duContext.data();
1372  while(functionContext && !functionContext->owner())
1373    functionContext = functionContext->parentContext();
1374  if(functionContext && functionContext->owner()) {
1375    FunctionType::Ptr funType = functionContext->owner()->type<FunctionType>();
1376    if(funType && funType->returnType()) {
1377        items << CompletionTreeItemPointer( new TypeConversionCompletionItem( "return " + funType->returnType()->toString(), funType->returnType()->indexed(), depth(), KSharedPtr <Cpp::CodeCompletionContext >(this) ) );
1378    }
1379  }
1380  return items;
1381}
1382
1383QList<CompletionTreeItemPointer> CodeCompletionContext::caseAccessCompletionItems()
1384{
1385  QList<CompletionTreeItemPointer> items;
1386
1387  IndexedType switchExprType = switchExpressionType(m_duContext);
1388
1389  LOCKDUCHAIN; if (!m_duContext) return items;
1390
1391  if (switchExprType.abstractType())
1392    items << CompletionTreeItemPointer( new TypeConversionCompletionItem( "case " + switchExprType.abstractType()->toString(), switchExprType, depth(), KSharedPtr <Cpp::CodeCompletionContext >(this) ) );
1393  return items;
1394}
1395
1396QList<CompletionTreeItemPointer> CodeCompletionContext::templateAccessCompletionItems()
1397{
1398  QList<CompletionTreeItemPointer> items;
1399  LOCKDUCHAIN; if (!m_duContext) return items;
1400
1401  AbstractType::Ptr type = m_expressionResult.type.abstractType();
1402  IdentifiedType* identified = dynamic_cast<IdentifiedType*>(type.unsafeData());
1403  Declaration* decl = 0;
1404  if(identified)
1405    decl = identified->declaration( m_duContext->topContext());
1406  if(!decl && !m_expressionResult.allDeclarations.isEmpty())
1407    decl = m_expressionResult.allDeclarations[0].getDeclaration(m_duContext->topContext());
1408  if(decl) {
1409    NormalDeclarationCompletionItem* item = new NormalDeclarationCompletionItem( KDevelop::DeclarationPointer(decl),  KDevelop::CodeCompletionContext::Ptr(this), 0, 0 );
1410    item->m_isTemplateCompletion = true;
1411    items << CompletionTreeItemPointer( item );
1412  }else{
1413    items += missingIncludeCompletionItems(m_expression, QString(), m_expressionResult, m_duContext.data(), depth(), true );
1414  }
1415  return items;
1416}
1417
1418QList<CompletionTreeItemPointer> CodeCompletionContext::commonFunctionAccessCompletionItems( bool fullCompletion )
1419{
1420  QList<CompletionTreeItemPointer> items;
1421
1422  uint max = MoreArgumentHintsCompletionItem::resetMaxArgumentHints(!fullCompletion);
1423
1424  if(functions().isEmpty() && m_accessType != BinaryOpFunctionCallAccess) {
1425    items += missingIncludeCompletionItems(m_expression, QString(), m_expressionResult, m_duContext.data(), depth(), true );
1426    return items;
1427  }
1428
1429  uint num = 0;
1430  foreach( const Cpp::CodeCompletionContext::Function &function, functions() ) {
1431    if (num == max) {
1432      //When there are too many overloaded functions, do not show them all
1433      CompletionTreeItemPointer item( new MoreArgumentHintsCompletionItem( KDevelop::CodeCompletionContext::Ptr(this), i18ncp("Here, overload is used as a programming term.  This string is used to display how many overloaded versions there are of the function whose name is the second argument.", "1 more overload of %2 (show more)", "%1 more overloads of %2 (show more)", functions().count() - num, functionName()), num ) );
1434      items.push_front(item);
1435      break;
1436    }
1437
1438    items << CompletionTreeItemPointer( new NormalDeclarationCompletionItem( function.function.declaration(), KDevelop::CodeCompletionContext::Ptr(this), 0, num ) );
1439    ++num;
1440  }
1441
1442  return items;
1443}
1444
1445QList< CompletionTreeItemPointer > CodeCompletionContext::binaryFunctionAccessCompletionItems( bool fullCompletion )
1446{
1447  QList<CompletionTreeItemPointer> items;
1448  LOCKDUCHAIN; if (!m_duContext) return items;
1449
1450  items += commonFunctionAccessCompletionItems(fullCompletion);
1451
1452  //Argument-hints for builtin operators
1453  AbstractType::Ptr type = m_expressionResult.type.abstractType();
1454  if(!m_expressionResult.isValid() || !m_expressionResult.isInstance || !type)
1455    return items;
1456
1457  IntegralType::Ptr integral = type.cast<IntegralType>();
1458
1459  if(!integral && (ARITHMETIC_COMPARISON_OPERATORS.contains(m_operator) || BINARY_ARITHMETIC_OPERATORS.contains(m_operator))) {
1460    ///There is one more chance: If the type can be converted to an integral type, C++ will convert it first, and then
1461    ///apply its builtin operators
1462    integral = IntegralType::Ptr(new IntegralType(KDevelop::IntegralType::TypeInt));
1463    TypeConversion conv(m_duContext->topContext());
1464    if(!conv.implicitConversion(m_expressionResult.type, integral->indexed()))
1465      integral = IntegralType::Ptr(); //No conversion possible
1466  }
1467
1468  if( m_operator == "[]" && (type.cast<KDevelop::ArrayType>() || type.cast<KDevelop::PointerType>())) {
1469    IntegralType::Ptr t(new IntegralType(IntegralType::TypeInt));
1470    t->setModifiers(IntegralType::UnsignedModifier);
1471    QString showName = "operator []";
1472    items << CompletionTreeItemPointer( new TypeConversionCompletionItem( showName, t->indexed(), depth(), KSharedPtr <Cpp::CodeCompletionContext >(this) ) );
1473  }
1474
1475  if( m_operator == "=" || integral ) {
1476    ///Conversion to the left operand-type, builtin operators on integral types
1477    IndexedType useType = integral ? integral->indexed() : m_expressionResult.type;
1478    QString showName = functionName();
1479    if(useType.abstractType())
1480      showName = useType.abstractType()->toString() + " " + m_operator;
1481
1482    if(useType == m_expressionResult.type && m_expressionResult.allDeclarations.size() == 1) {
1483      Declaration* decl = m_expressionResult.allDeclarations[0].getDeclaration(m_duContext->topContext());
1484      if(decl)
1485        showName = decl->toString() + " " + m_operator;
1486    }
1487
1488    items << CompletionTreeItemPointer( new TypeConversionCompletionItem( showName, useType, depth(), KSharedPtr <Cpp::CodeCompletionContext >(this) ) );
1489  }
1490
1491  return items;
1492}
1493
1494QList<CompletionTreeItemPointer> CodeCompletionContext::functionAccessCompletionItems(bool fullCompletion)
1495{
1496  QList<CompletionTreeItemPointer> items;
1497  LOCKDUCHAIN; if (!m_duContext) return items;
1498
1499  items += commonFunctionAccessCompletionItems(fullCompletion);
1500
1501  if(!m_expressionResult.isValid() ||
1502     !m_expressionResult.type.abstractType() ||
1503     (m_expressionResult.isInstance && !m_expressionIsTypePrefix) ||
1504     m_expressionResult.type.type<FunctionType>())
1505    return items;
1506
1507  //Eventually add a builtin copy-constructor if a type is being constructed
1508  if(!hasCopyConstructor(m_expressionResult.type.type<CppClassType>(), m_duContext->topContext()) &&
1509      m_knownArgumentExpressions.isEmpty())
1510  {
1511      QString showName = m_expressionResult.type.abstractType()->toString() + "(";
1512      items << CompletionTreeItemPointer( new TypeConversionCompletionItem( showName, m_expressionResult.type, depth(), KSharedPtr <Cpp::CodeCompletionContext >(this) ) );
1513  }
1514
1515  return items;
1516}
1517
1518QList<CompletionTreeItemPointer> CodeCompletionContext::includeListAccessCompletionItems(const bool& shouldAbort)
1519{
1520  QList<CompletionTreeItemPointer> items;
1521
1522  QList<KDevelop::IncludeItem> allIncludeItems = includeItems();
1523  foreach(const KDevelop::IncludeItem& includeItem, allIncludeItems) {
1524    if (shouldAbort)
1525      return items;
1526
1527    items << CompletionTreeItemPointer( new IncludeFileCompletionItem(includeItem) );
1528  }
1529
1530  return items;
1531}
1532
1533QList<CompletionTreeItemPointer> CodeCompletionContext::signalSlotAccessCompletionItems()
1534{
1535  QList<CompletionTreeItemPointer> items;
1536  LOCKDUCHAIN; if (!m_duContext) return items;
1537
1538  KDevelop::IndexedDeclaration connectedSignal;
1539  if(!m_connectedSignalIdentifier.isEmpty()) {
1540    ///Create an additional argument-hint context that shows information about the signal we connect to
1541    if(parentContext() && parentContext()->m_knownArgumentTypes.count() > 1 && parentContext()->m_knownArgumentTypes[0].type.isValid()) {
1542      StructureType::Ptr signalContainerType = TypeUtils::targetType(parentContext()->m_knownArgumentTypes[0].type.abstractType(), m_duContext->topContext()).cast<StructureType>();
1543      if(signalContainerType) {
1544//             kDebug() << "searching signal in container" << signalContainerType->toString() << m_connectedSignalIdentifier.toString();
1545          Declaration* signalContainer = signalContainerType->declaration(m_duContext->topContext());
1546        if(signalContainer && signalContainer->internalContext()) {
1547          IndexedString signature(m_connectedSignalNormalizedSignature);
1548          foreach(const DeclarationDepthPair &decl, signalContainer->internalContext()->allDeclarations( CursorInRevision::invalid(), m_duContext->topContext(), false )) {
1549            if(decl.first->identifier() == m_connectedSignalIdentifier) {
1550              if(QtFunctionDeclaration* classFun = dynamic_cast<QtFunctionDeclaration*>(decl.first)) {
1551                if(classFun->isSignal() && classFun->normalizedSignature() == signature) {
1552                  //Match
1553                  NormalDeclarationCompletionItem* item = new NormalDeclarationCompletionItem( DeclarationPointer(decl.first), KDevelop::CodeCompletionContext::Ptr(parentContext()), decl.second + 50);
1554                  item->useAlternativeText = true;
1555                  m_connectedSignal = IndexedDeclaration(decl.first);
1556                  item->alternativeText = i18n("Connect to %1 (%2)", decl.first->qualifiedIdentifier().toString(), QString::fromUtf8(m_connectedSignalNormalizedSignature) );
1557                  item->m_isQtSignalSlotCompletion = true;
1558                  items << CompletionTreeItemPointer(item);
1559                  connectedSignal = IndexedDeclaration(decl.first);
1560                }
1561              }
1562            }
1563          }
1564        }
1565      }
1566    }
1567  }
1568  if( memberAccessContainer().isValid() ) {
1569    QList<CompletionTreeItemPointer> signalSlots;
1570    ///Collect all slots/signals to show
1571    AbstractType::Ptr type = memberAccessContainer().type.abstractType();
1572    IdentifiedType* identified = dynamic_cast<IdentifiedType*>(type.unsafeData());
1573    if(identified) {
1574      Declaration* decl = identified->declaration(m_duContext->topContext());
1575      if(decl && decl->internalContext() /*&& Cpp::findLocalDeclarations(decl->internalContext(), Identifier("QObject"), m_duContext->topContext()).count()*/) { //hacky test whether it's a QObject
1576        ///@todo Always allow this when the class is within one of the open projects. Problem: The project lookup is not threadsafe
1577        if(connectedSignal.isValid() && m_localClass.data() == decl->internalContext()) { ///Create implementation-helper to add a slot
1578          signalSlots << CompletionTreeItemPointer(new ImplementationHelperItem(ImplementationHelperItem::CreateSignalSlot, DeclarationPointer(connectedSignal.data()), CodeCompletionContext::Ptr(this)));
1579        }
1580
1581        foreach(const DeclarationDepthPair &candidate, decl->internalContext()->allDeclarations(CursorInRevision::invalid(), m_duContext->topContext(), false) ) {
1582          if(QtFunctionDeclaration* classFun = dynamic_cast<QtFunctionDeclaration*>(candidate.first)) {
1583            if((classFun->isSignal() && m_onlyShow != ShowSlots) || (accessType() == SlotAccess && classFun->isSlot() && filterDeclaration(classFun))) {
1584              NormalDeclarationCompletionItem* item = new NormalDeclarationCompletionItem( DeclarationPointer(candidate.first), KDevelop::CodeCompletionContext::Ptr(this), candidate.second );
1585              item->m_isQtSignalSlotCompletion = true;
1586              if(!m_connectedSignalIdentifier.isEmpty()) {
1587                item->m_fixedMatchQuality = 0;
1588                //Compute a match-quality, by comparing the strings
1589                QByteArray thisSignature = classFun->normalizedSignature().byteArray();
1590                if(m_connectedSignalNormalizedSignature.startsWith(thisSignature) || (m_connectedSignalNormalizedSignature.isEmpty() && thisSignature.isEmpty())) {
1591                  QByteArray remaining = m_connectedSignalNormalizedSignature.mid(thisSignature.length());
1592                  int remainingElements = remaining.split(',').count();
1593                  if(remaining.isEmpty())
1594                    item->m_fixedMatchQuality = 10;
1595                  else if(remainingElements < 4)
1596                    item->m_fixedMatchQuality  = 6 - remainingElements;
1597                  else
1598                    item->m_fixedMatchQuality = 2;
1599                }
1600              }else{
1601                item->m_fixedMatchQuality = 10;
1602              }
1603              signalSlots << CompletionTreeItemPointer( item );
1604            }
1605          }
1606        }
1607
1608        eventuallyAddGroup(i18n("Signals/Slots"), 10, signalSlots);
1609      }
1610    }
1611  }
1612  return items;
1613}
1614
1615QList< CompletionTreeItemPointer > CodeCompletionContext::standardAccessCompletionItems() {
1616  QList<CompletionTreeItemPointer> items;
1617  LOCKDUCHAIN; if (!m_duContext) return items;
1618  //Normal case: Show all visible declarations
1619  QSet<QualifiedIdentifier> hadNamespaceDeclarations;
1620
1621  bool typeIsConst = false;
1622  if (Declaration* func = Cpp::localFunctionFromCodeContext(m_duContext.data())) {
1623    if (func->abstractType() && (func->abstractType()->modifiers() & AbstractType::ConstModifier))
1624      typeIsConst = true;
1625  }
1626
1627  QList<DeclarationDepthPair> decls = m_duContext->allDeclarations(m_duContext->type() == DUContext::Class ? m_duContext->range().end : m_position, m_duContext->topContext());
1628
1629  //Collect the contents of unnamed namespaces
1630  QList<Declaration*> unnamed = m_duContext->findDeclarations(QualifiedIdentifier(unnamedNamespaceIdentifier().identifier()), m_position);
1631  foreach(Declaration* ns, unnamed)
1632    if(ns->kind() == Declaration::Namespace && ns->internalContext())
1633      decls += ns->internalContext()->allDeclarations(m_position, m_duContext->topContext(), false);
1634
1635  //Collect the Declarations from all "using namespace" imported contexts
1636  QList<Declaration*> imports = m_duContext->findDeclarations( globalImportIdentifier(), m_position, 0, DUContext::NoFiltering );
1637
1638  QSet<QualifiedIdentifier> ids;
1639  foreach(Declaration* importDecl, imports) {
1640    NamespaceAliasDeclaration* aliasDecl = dynamic_cast<NamespaceAliasDeclaration*>(importDecl);
1641    if(aliasDecl) {
1642      ids.insert(aliasDecl->importIdentifier());
1643    }else{
1644      kDebug() << "Import is not based on NamespaceAliasDeclaration";
1645    }
1646  }
1647
1648  QualifiedIdentifier ownNamespaceScope = Cpp::namespaceScopeComponentFromContext(m_duContext->scopeIdentifier(true), m_duContext.data(), m_duContext->topContext());
1649  if(!ownNamespaceScope.isEmpty())
1650    for(int a = 1; a <= ownNamespaceScope.count(); ++a)
1651      ids += ownNamespaceScope.left(a);
1652
1653  foreach(const QualifiedIdentifier &id, ids) {
1654    QList<Declaration*> importedContextDecls = m_duContext->findDeclarations( id );
1655    foreach(Declaration* contextDecl, importedContextDecls) {
1656      if(contextDecl->kind() != Declaration::Namespace || !contextDecl->internalContext())
1657        continue;
1658      DUContext* context = contextDecl->internalContext();
1659
1660      if(context->range().contains(m_duContext->range()) && context->url() == m_duContext->url())
1661        continue; //If the context surrounds the current one, the declarations are visible through allDeclarations(..).
1662      foreach(Declaration* decl, context->localDeclarations()) {
1663        if(filterDeclaration(decl))
1664          decls << qMakePair(decl, 1200);
1665      }
1666    }
1667  }
1668
1669  QList<DeclarationDepthPair> oldDecls = decls;
1670  decls.clear();
1671 
1672  //Remove pure function-definitions before doing overload-resolution, so they don't hide their own declarations.
1673  foreach( const DeclarationDepthPair& decl, oldDecls )
1674    if(!dynamic_cast<FunctionDefinition*>(decl.first) || !static_cast<FunctionDefinition*>(decl.first)->hasDeclaration()) {
1675      if(decl.first->kind() == Declaration::Namespace) {
1676        QualifiedIdentifier id = decl.first->qualifiedIdentifier();
1677        if(hadNamespaceDeclarations.contains(id))
1678          continue;
1679       
1680        hadNamespaceDeclarations.insert(id);
1681      }
1682
1683      if(filterDeclaration(decl.first, 0, true)) {
1684        decls << decl;
1685      }
1686    }
1687   
1688  decls = Cpp::hideOverloadedDeclarations(decls, typeIsConst);
1689
1690  foreach( const DeclarationDepthPair& decl, decls )
1691    items << CompletionTreeItemPointer( new NormalDeclarationCompletionItem(DeclarationPointer(decl.first), KDevelop::CodeCompletionContext::Ptr(this), decl.second ) );
1692
1693  ///Eventually show additional specificly known items for the matched argument-type, like for example enumerators for enum types
1694  CodeCompletionContext* parent = parentContext();
1695  if(parent) {
1696    if(parent->accessType() == FunctionCallAccess) {
1697      foreach(const Cpp::OverloadResolutionFunction& function, parent->functions()) {
1698        if(function.function.isValid() && function.function.isViable() && function.function.declaration()) {
1699          //uint parameterNumber = parent->m_knownArgumentExpressions.size() + function.matchedArguments;
1700          Declaration* functionDecl = function.function.declaration().data();
1701          if(functionDecl->type<FunctionType>()->arguments().count() > function.matchedArguments) {
1702            items += specialItemsForArgumentType(functionDecl->type<FunctionType>()->arguments()[function.matchedArguments]);
1703          }
1704        }
1705      }
1706    }
1707    else if (parent->accessType() == BinaryOpFunctionCallAccess)
1708    {
1709      items += specialItemsForArgumentType(parent->m_expressionResult.type.abstractType());
1710    }
1711  }
1712
1713  return items;
1714}
1715
1716void CodeCompletionContext::addOverridableItems()
1717{
1718  if(m_duContext->type() != DUContext::Class)
1719    return;
1720
1721  //Show override helper items
1722  QMap< QPair<IndexedType, IndexedString>, KDevelop::CompletionTreeItemPointer > overridable;
1723  foreach(const DUContext::Import &import, m_duContext->importedParentContexts())
1724  {
1725    DUContext* ctx = import.context(m_duContext->topContext());
1726    if(ctx)
1727      getOverridable(m_duContext.data(), ctx, overridable, Ptr(this));
1728  }
1729
1730  if(!overridable.isEmpty())
1731    eventuallyAddGroup(i18n("Virtual Override"), 0, overridable.values());
1732}
1733
1734void CodeCompletionContext::addImplementationHelpers()
1735{
1736  QList<CompletionTreeItemPointer> helpers = getImplementationHelpers();
1737  if(!helpers.isEmpty()) {
1738    eventuallyAddGroup(i18n("Implement Function"), 0, helpers);
1739  }
1740}
1741
1742void CodeCompletionContext::addCPPBuiltin()
1743{
1744  ///Eventually add a "this" item
1745  DUContext* functionContext = m_duContext.data();
1746  if(m_onlyShow != ShowSignals && m_onlyShow != ShowSlots && m_onlyShow != ShowTypes) {
1747    while(functionContext && functionContext->type() == DUContext::Other && functionContext->parentContext() && functionContext->parentContext()->type() == DUContext::Other)
1748      functionContext = functionContext->parentContext();
1749  }
1750
1751  ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(DUChainUtils::declarationForDefinition(functionContext->owner(), m_duContext->topContext()));
1752 
1753  if(classFun && !classFun->isStatic() && classFun->context()->owner()
1754              && m_onlyShow != ShowSignals && m_onlyShow != ShowSlots && m_onlyShow != ShowTypes)
1755  {
1756    AbstractType::Ptr classType = classFun->context()->owner()->abstractType();
1757    if(classFun->abstractType()->modifiers() & AbstractType::ConstModifier)
1758      classType->setModifiers((AbstractType::CommonModifiers)(classType->modifiers() | AbstractType::ConstModifier));
1759    PointerType::Ptr thisPointer(new PointerType());
1760    thisPointer->setModifiers(AbstractType::ConstModifier);
1761    thisPointer->setBaseType(classType);
1762    KSharedPtr<TypeConversionCompletionItem> item( new TypeConversionCompletionItem("this", thisPointer->indexed(), 0, KSharedPtr <Cpp::CodeCompletionContext >(this)) );
1763    item->setPrefix(thisPointer->toString());
1764    QList<CompletionTreeItemPointer> lst;
1765    lst += CompletionTreeItemPointer(item.data());
1766    eventuallyAddGroup(i18n("C++ Builtin"), 800, lst);
1767  }
1768  eventuallyAddGroup(i18n("C++ Builtin"), 800, keywordCompletionItems());
1769}
1770
1771bool CodeCompletionContext::shouldAddParentItems(bool fullCompletion)
1772{
1773  if (!m_parentContext)
1774    return false;
1775
1776  if ( !fullCompletion && (!Cpp::useArgumentHintInAutomaticCompletion() || depth() != 0) )
1777    return false;
1778
1779  if ( NO_MULTIPLE_BINARY_OPERATORS && m_accessType == BinaryOpFunctionCallAccess &&
1780                                       parentContext()->m_accessType == BinaryOpFunctionCallAccess )
1781    return false;
1782
1783  return true;
1784}
1785
1786QList<CompletionTreeItemPointer> CodeCompletionContext::completionItems(bool& shouldAbort, bool fullCompletion) {
1787    QList<CompletionTreeItemPointer> items;
1788    if(!m_valid)
1789      return items;
1790
1791    switch(m_accessType) {
1792      case MemberAccess:
1793      case ArrowMemberAccess:
1794      case StaticMemberChoose:
1795      case MemberChoose:
1796        items += memberAccessCompletionItems(shouldAbort);
1797        break;
1798      case ReturnAccess:
1799        items += returnAccessCompletionItems();
1800        break;
1801      case CaseAccess:
1802        items += caseAccessCompletionItems();
1803        break;
1804      case TemplateAccess:
1805        items += templateAccessCompletionItems();
1806        break;
1807      case FunctionCallAccess:
1808        items += functionAccessCompletionItems(fullCompletion);
1809        break;
1810      case BinaryOpFunctionCallAccess:
1811        items += binaryFunctionAccessCompletionItems(fullCompletion);
1812        break;
1813      case IncludeListAccess:
1814        items += includeListAccessCompletionItems(shouldAbort);
1815        break;
1816      case SignalAccess:
1817      case SlotAccess:
1818        items += signalSlotAccessCompletionItems();
1819        //Since there is 2 connect() functions, the third argument may be a slot as well as a QObject*, so also
1820        //give normal completion items
1821        if(parentContext() && parentContext()->m_knownArgumentExpressions.size() != 2)
1822          break;
1823      default:
1824        if(depth() == 0 && (m_onlyShow == ShowAll || m_onlyShow == ShowTypes))
1825        {
1826          items += standardAccessCompletionItems();
1827          LOCKDUCHAIN; if (!m_duContext) return items;
1828#ifndef TEST_COMPLETION
1829          MissingIncludeCompletionModel::self().startWithExpression(m_duContext, QString(), m_followingText);
1830#endif
1831          addCPPBuiltin();
1832        }
1833        break;
1834    }
1835
1836    if(shouldAddParentItems(fullCompletion))
1837      items = parentContext()->completionItems( shouldAbort, fullCompletion ) + items;
1838
1839    if(depth() == 0)
1840    {
1841      LOCKDUCHAIN; if (!m_duContext) return items;
1842      //Eventually add missing include-completion in cases like SomeNamespace::NotIncludedClass|
1843      if(m_accessType == StaticMemberChoose) {
1844#ifndef TEST_COMPLETION
1845        MissingIncludeCompletionModel::self().startWithExpression(m_duContext, m_expression + "::", m_followingText);
1846#endif
1847      }
1848
1849      if (!parentContext())
1850        addOverridableItems();
1851      if (isImplementationHelperValid())
1852        addImplementationHelpers();
1853    }
1854
1855    return items;
1856}
1857
1858QList<CompletionTreeItemPointer> CodeCompletionContext::getImplementationHelpers() {
1859  QList<CompletionTreeItemPointer> ret;
1860  TopDUContext* searchInContext = m_duContext->topContext();
1861
1862  if(searchInContext)
1863    ret += getImplementationHelpersInternal(m_duContext->scopeIdentifier(true), searchInContext);
1864
1865  if(!CppUtils::isHeader( searchInContext->url().toUrl() )) {
1866    KUrl headerUrl = CppUtils::sourceOrHeaderCandidate( searchInContext->url().toUrl(), true );
1867    searchInContext = ICore::self()->languageController()->language("C++")->languageSupport()->standardContext(headerUrl);
1868    if(searchInContext)
1869      ret += getImplementationHelpersInternal(m_duContext->scopeIdentifier(true), searchInContext);
1870  }
1871
1872  return ret;
1873}
1874
1875QList<CompletionTreeItemPointer> CodeCompletionContext::getImplementationHelpersInternal(const QualifiedIdentifier& minimumScope, DUContext* context)
1876{
1877  QList<CompletionTreeItemPointer> ret;
1878
1879  foreach(Declaration* decl, context->localDeclarations()) {
1880    if (decl->range().isEmpty() || decl->isDefinition() || FunctionDefinition::definition(decl)) {
1881      continue;
1882    }
1883    if (!decl->qualifiedIdentifier().toString().startsWith(minimumScope.toString())) {
1884      continue;
1885    }
1886    AbstractFunctionDeclaration* funDecl = dynamic_cast<AbstractFunctionDeclaration*>(decl);
1887    if (!funDecl) {
1888      continue;
1889    }
1890    ClassFunctionDeclaration* classFun = dynamic_cast<ClassFunctionDeclaration*>(decl);
1891    if (classFun && (classFun->isAbstract() || classFun->isSignal())) {
1892      continue;
1893    }
1894    ret << KDevelop::CompletionTreeItemPointer(
1895      new ImplementationHelperItem( ImplementationHelperItem::CreateDefinition,
1896                                    DeclarationPointer(decl),
1897                                    KSharedPtr<CodeCompletionContext>(this)));
1898  }
1899
1900  foreach(DUContext* child, context->childContexts()) {
1901    if(child->type() == DUContext::Namespace
1902        || child->type() == DUContext::Class
1903        || child->type() == DUContext::Helper)
1904    {
1905      ret += getImplementationHelpersInternal(minimumScope, child);
1906    }
1907  }
1908
1909  return ret;
1910}
1911
1912QualifiedIdentifier CodeCompletionContext::requiredPrefix(Declaration* decl) const {
1913  QualifiedIdentifier worstCase = decl->context()->scopeIdentifier(true);
1914  if(!m_duContext)
1915    return worstCase;
1916  QualifiedIdentifier currentPrefix;
1917
1918  while(1) {
1919    QList<Declaration*> found = m_duContext->findDeclarations( currentPrefix + decl->identifier() );
1920    if(found.contains(decl))
1921      return currentPrefix;
1922
1923    if(currentPrefix.count() >= worstCase.count()) {
1924      return worstCase;
1925    }else {
1926      currentPrefix.push(worstCase.at(currentPrefix.count()));
1927    }
1928  }
1929}
1930
1931QList< KSharedPtr< KDevelop::CompletionTreeItem > > CodeCompletionContext::specialItemsForArgumentType(TypePtr< KDevelop::AbstractType > type) {
1932  QList< KSharedPtr< KDevelop::CompletionTreeItem > > items;
1933  if(EnumerationType::Ptr enumeration = TypeUtils::realType(type, m_duContext->topContext()).cast<EnumerationType>()) {
1934    Declaration* enumDecl = enumeration->declaration(m_duContext->topContext());
1935    if(enumDecl && enumDecl->internalContext()) {
1936
1937      QualifiedIdentifier prefix = requiredPrefix(enumDecl);
1938
1939      DUContext* enumInternal = enumDecl->internalContext();
1940      foreach(Declaration* enumerator, enumInternal->localDeclarations()) {
1941        QualifiedIdentifier id = prefix + enumerator->identifier();
1942        items << CompletionTreeItemPointer(new NormalDeclarationCompletionItem( DeclarationPointer(enumerator), KDevelop::CodeCompletionContext::Ptr(this), 0 ));
1943        static_cast<NormalDeclarationCompletionItem*>(items.back().data())->alternativeText = id.toString();
1944        static_cast<NormalDeclarationCompletionItem*>(items.back().data())->useAlternativeText = true;
1945      }
1946    }
1947  }
1948  return items;
1949}
1950
1951bool CodeCompletionContext::visibleFromWithin(KDevelop::Declaration* decl, DUContext* currentContext) {
1952  if(!decl || !currentContext)
1953    return false;
1954  if(currentContext->imports(decl->context()))
1955    return true;
1956 
1957  return visibleFromWithin(decl, currentContext->parentContext());
1958}
1959
1960/**
1961 * see @p type as function type and try to get it's return type as IntegralType data type.
1962 */
1963static inline int getIntegralReturnType(const AbstractType::Ptr& type)
1964{
1965  if (!type)
1966    return -1;
1967  const FunctionType::Ptr funcType = type.cast<FunctionType>();
1968  if (!funcType || !funcType->returnType())
1969    return -1;
1970  const IntegralType::Ptr intType = funcType->returnType().cast<IntegralType>();
1971  if (!intType)
1972    return -1;
1973  return intType->dataType();
1974}
1975
1976bool  CodeCompletionContext::filterDeclaration(Declaration* decl, DUContext* declarationContext, bool dynamic) {
1977  if(!decl)
1978    return true;
1979
1980  if(dynamic_cast<TemplateParameterDeclaration*>(decl) && !visibleFromWithin(decl, m_duContext.data()))
1981    return false;
1982 
1983  static IndexedIdentifier friendIdentifier(Identifier("friend"));
1984  static IndexedIdentifier globalImport(globalImportIdentifier());
1985 
1986  if(decl->indexedIdentifier().isEmpty()) //Filter out nameless declarations
1987    return false;
1988
1989  if(decl->indexedIdentifier() == friendIdentifier || decl->indexedIdentifier() == Cpp::unnamedNamespaceIdentifier()
1990     || decl->indexedIdentifier() == globalImport)
1991    return false;
1992 
1993  if(excludeReservedIdentifiers)
1994  {
1995    //Exclude identifiers starting with "__" or "_Uppercase"
1996    IndexedString str = decl->indexedIdentifier().identifier().identifier();
1997    const char* cstr = str.c_str();
1998    if(str.length() > 2 && cstr[0] == '_' && (cstr[1] == '_' || QChar(cstr[1]).isUpper()) && decl->url() != m_duContext->url())
1999      return false;
2000  }
2001
2002  if(ClassDeclaration* cDecl = dynamic_cast<ClassDeclaration*>(decl)) {
2003    ///TODO: indexedIdentifier().isEmpty() should be fixed for this case...
2004    if (cDecl->classType() == ClassDeclarationData::Struct && cDecl->identifier().toString().isEmpty()) {
2005      // filter anonymous structs
2006      return false;
2007    }
2008  }
2009
2010  if(m_onlyShow == ShowTypes && decl->kind() != Declaration::Type && decl->kind() != Declaration::Namespace
2011     && decl->kind() != Declaration::NamespaceAlias )
2012    return false;
2013 
2014  if(m_onlyShow == ShowVariables && (decl->kind() != Declaration::Instance || decl->isFunctionDeclaration()))
2015    return false;
2016 
2017  if(m_onlyShow == ShowImplementationHelpers)
2018    return false; //Implementation helpers don't come here
2019   
2020  if(m_onlyShow == ShowSignals || m_onlyShow == ShowSlots) {
2021    Cpp::QtFunctionDeclaration* qtFunction = dynamic_cast<Cpp::QtFunctionDeclaration*>(decl);
2022    if(!qtFunction || (m_onlyShow == ShowSignals && !qtFunction->isSignal())
2023                   || (m_onlyShow == ShowSlots && !qtFunction->isSlot()))
2024      return false;
2025  }
2026 
2027  if(dynamic && decl->context()->type() == DUContext::Class) {
2028    ClassMemberDeclaration* classMember = dynamic_cast<ClassMemberDeclaration*>(decl);
2029    if(classMember)
2030      return filterDeclaration(classMember, declarationContext);
2031  }
2032
2033  // https://bugs.kde.org/show_bug.cgi?id=206376
2034  // hide void functions in expressions but don't hide signals / slots with void return type
2035  if (m_onlyShow != ShowSignals && m_onlyShow != ShowSlots
2036      && m_parentContext && decl->isFunctionDeclaration()
2037      && getIntegralReturnType(decl->abstractType()) == IntegralType::TypeVoid)
2038  {
2039    const ExpressionEvaluationResult& result =
2040            static_cast<CodeCompletionContext*>(m_parentContext.data())->m_expressionResult;
2041    // for now only hide in non-lvalue expressions so we don't get problems in sig/slot connections e.g.
2042    if (result.type.isValid() && !result.isLValue())
2043      return false;
2044  }
2045
2046  return true;
2047}
2048
2049bool  CodeCompletionContext::filterDeclaration(ClassMemberDeclaration* decl, DUContext* declarationContext) {
2050  if(m_doAccessFiltering && decl) {
2051    if(!Cpp::isAccessible(m_localClass ? m_localClass.data() : m_duContext.data(), decl, m_duContext->topContext(), declarationContext))
2052      return false;
2053  }
2054  // filter properties from code completion, they mostly have to be accessed via their getter/setters
2055  if (dynamic_cast<QPropertyDeclaration*>(decl)) {
2056    return false;
2057  }
2058  return filterDeclaration((Declaration*)decl, declarationContext, false);
2059}
2060
2061void CodeCompletionContext::replaceCurrentAccess(QString old, QString _new)
2062{
2063  //We must not change the document from within the background, so we use a queued connection to an object created in the foregroud
2064  QMetaObject::invokeMethod(&accessReplacer, "exec", Qt::QueuedConnection, Q_ARG(KUrl, m_duContext->url().toUrl()), Q_ARG(QString, old), Q_ARG(QString, _new));
2065}
2066
2067int CodeCompletionContext::matchPosition() const {
2068  return m_knownArgumentExpressions.count();
2069}
2070
2071void CodeCompletionContext::eventuallyAddGroup(QString name, int priority, QList< KSharedPtr< KDevelop::CompletionTreeItem > > items) {
2072  if(items.isEmpty())
2073    return;
2074  KDevelop::CompletionCustomGroupNode* node = new KDevelop::CompletionCustomGroupNode(name, priority);
2075  node->appendChildren(items);
2076  m_storedUngroupedItems << CompletionTreeElementPointer(node);
2077}
2078
2079QList< KSharedPtr< KDevelop::CompletionTreeItem > > CodeCompletionContext::keywordCompletionItems() {
2080  QList<CompletionTreeItemPointer> ret;
2081  #ifdef TEST_COMPLETION
2082  return ret;
2083  #endif
2084  #define ADD_TYPED_TOKEN_S(X, type) ret << CompletionTreeItemPointer( new TypeConversionCompletionItem(X, type, 0, KSharedPtr<Cpp::CodeCompletionContext>(this)) )
2085  #define ADD_TYPED_TOKEN(X, type) ADD_TYPED_TOKEN_S(#X, type)
2086 
2087  #define ADD_TOKEN(X) ADD_TYPED_TOKEN(X, KDevelop::IndexedType())
2088  #define ADD_TOKEN_S(X) ADD_TYPED_TOKEN_S(X, KDevelop::IndexedType())
2089
2090  bool restrictedItems = (m_onlyShow == ShowSignals) ||
2091                         (m_onlyShow == ShowSlots) || 
2092                         (m_onlyShow == ShowTypes) ||
2093                         (m_onlyShow == ShowImplementationHelpers);
2094 
2095  if(!restrictedItems || m_onlyShow == ShowTypes) {
2096    ADD_TOKEN(bool);
2097    ADD_TOKEN(char);
2098    ADD_TOKEN(char16_t);
2099    ADD_TOKEN(char32_t);
2100    ADD_TOKEN(const);
2101    ADD_TOKEN(double);
2102    ADD_TOKEN(enum);
2103    ADD_TOKEN(float);
2104    ADD_TOKEN(int);
2105    ADD_TOKEN(long);
2106    ADD_TOKEN(mutable);
2107    ADD_TOKEN(register);
2108    ADD_TOKEN(short);
2109    ADD_TOKEN(signed);
2110    ADD_TOKEN(struct);
2111    ADD_TOKEN(template);
2112    ADD_TOKEN(typename);
2113    ADD_TOKEN(union);
2114    ADD_TOKEN(unsigned);
2115    ADD_TOKEN(void);
2116    ADD_TOKEN(volatile);
2117    ADD_TOKEN(wchar_t);
2118  }
2119 
2120  if(restrictedItems && (m_duContext->type() == DUContext::Other || m_duContext->type() == DUContext::Function))
2121    return ret;
2122 
2123  if(m_duContext->type() == DUContext::Class) {
2124    ADD_TOKEN_S("Q_OBJECT");
2125    ADD_TOKEN(private);
2126    ADD_TOKEN(protected);
2127    ADD_TOKEN(public);
2128    ADD_TOKEN_S("signals");
2129    ADD_TOKEN_S("slots");
2130    ADD_TOKEN(virtual);
2131    ADD_TOKEN(friend);
2132    ADD_TOKEN(explicit);
2133  }
2134 
2135  if(m_duContext->type() == DUContext::Other) {
2136    ADD_TOKEN(break);
2137    ADD_TOKEN(case);
2138    ADD_TOKEN(and);
2139    ADD_TOKEN(and_eq);
2140    ADD_TOKEN(asm);
2141    ADD_TOKEN(bitand);
2142    ADD_TOKEN(bitor);
2143    ADD_TOKEN(catch);
2144    ADD_TOKEN(const_cast);
2145    ADD_TOKEN(default);
2146    ADD_TOKEN(delete);
2147    ADD_TOKEN(do);
2148    ADD_TOKEN(dynamic_cast);
2149    ADD_TOKEN(else);
2150    ADD_TOKEN_S("emit");
2151    ADD_TOKEN(for);
2152    ADD_TOKEN(goto);
2153    ADD_TOKEN(if);
2154    ADD_TOKEN(incr);
2155    ADD_TOKEN(new);
2156    ADD_TOKEN(not);
2157    ADD_TOKEN(not_eq);
2158    ADD_TOKEN(nullptr);
2159    ADD_TOKEN(or);
2160    ADD_TOKEN(or_eq);
2161    ADD_TOKEN(reinterpret_cast);
2162    ADD_TOKEN(return);
2163    ADD_TOKEN(static_cast);
2164    ADD_TOKEN(switch);
2165    ADD_TOKEN(try);
2166    ADD_TOKEN(typeid);
2167    ADD_TOKEN(while);
2168    ADD_TOKEN(xor);
2169    ADD_TOKEN(xor_eq);
2170    ADD_TOKEN(continue);
2171  }else{
2172    ADD_TOKEN(inline);
2173  }
2174 
2175  if(m_duContext->type() == DUContext::Global) {
2176    ADD_TOKEN(export);
2177    ADD_TOKEN(extern);
2178    ADD_TOKEN(namespace);
2179  }
2180 
2181  ADD_TOKEN(auto);
2182  ADD_TOKEN(class);
2183  ADD_TOKEN(operator);
2184  ADD_TOKEN(sizeof);
2185  ADD_TOKEN(static);
2186  ADD_TOKEN(throw);
2187  ADD_TOKEN(typedef);
2188  ADD_TOKEN(using);
2189
2190  ConstantIntegralType::Ptr trueType(new ConstantIntegralType(IntegralType::TypeBoolean));
2191  trueType->setValue<bool>(true);
2192 
2193  ADD_TYPED_TOKEN(true, trueType->indexed());
2194
2195  ConstantIntegralType::Ptr falseType(new ConstantIntegralType(IntegralType::TypeBoolean));
2196  falseType->setValue<bool>(false);
2197
2198  ADD_TYPED_TOKEN(false, falseType->indexed());
2199 
2200  return ret;
2201}
2202
2203QString CodeCompletionContext::followingText() const {
2204  return m_followingText;
2205}
2206
2207void CodeCompletionContext::setFollowingText(QString str) {
2208  m_followingText = str.trimmed();
2209}
2210
2211
2212}