kde-extraapps/kdevelop/languages/cpp/codecompletion/context.h
2015-07-26 14:23:17 +03:00

361 lines
17 KiB
C++

/*
Copyright 2007-2009 David Nolden <david.nolden.kdevelop@art-master.de>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef CODECOMPLETIONCONTEXT_H
#define CODECOMPLETIONCONTEXT_H
#include <ksharedptr.h>
#include <language/duchain/duchainpointer.h>
#include "../cppduchain/typeconversion.h"
#include "../cppduchain/expressionevaluationresult.h"
#include <language/util/includeitem.h>
#include "item.h"
#include <language/codecompletion/codecompletioncontext.h>
namespace KTextEditor {
class View;
class Cursor;
}
namespace KDevelop {
class DUContext;
class AbstractType;
class CompletionTreeItem;
typedef KSharedPtr<CompletionTreeItem> CompletionTreeItemPointer;
typedef QPair<Declaration*, bool> DeclAccessPair;
}
namespace Cpp {
class OverloadResolutionFunction;
class ImplementationHelperItem;
#ifdef TEST_COMPLETION
int expressionBefore( const QString& _text, int index );
#endif
typedef QPair<Declaration*, int> DeclarationDepthPair;
/**
* This class is responsible for finding out what kind of completion is needed, what expression should be evaluated for the container-class of the completion, what conversion will be applied to the result of the completion, etc.
* */
class CodeCompletionContext : public KDevelop::CodeCompletionContext {
public:
///Computes the full set of completion items, using the information retrieved earlier.
///Should only be called on the first context, parent contexts are included in the computations.
///@param Abort is checked regularly, and if it is false, the computation is aborted.
virtual QList<CompletionTreeItemPointer> completionItems(bool& abort, bool fullCompletion = true);
virtual QList< KSharedPtr< KDevelop::CompletionTreeElement > > ungroupedElements();
typedef KSharedPtr<CodeCompletionContext> Ptr;
typedef OverloadResolutionFunction Function;
typedef QList<Function> FunctionList;
enum AccessType {
NoMemberAccess, /// With NoMemberAccess, a global completion should be done
MemberAccess, /// "Class."
ArrowMemberAccess, /// "Class->"
StaticMemberChoose, /// "Class::"
MemberChoose, /// "Class->ParentClass::"
SignalAccess, /// All signals from MemberAccessContainer should be listed
SlotAccess, /// All slots from MemberAccessContainer should be listed
IncludeListAccess, /// A list of include-files should be presented. Get the list through includeItems()
/// The following will never appear as initial accessType, but as a parentContext()
FunctionCallAccess, /// "function("
BinaryOpFunctionCallAccess, /// "var1 {somebinaryoperator} "
TemplateAccess, /// "bla<."
ReturnAccess, /// "return " -- Takes into account return type
CaseAccess, /// "case " -- Takes into account switch expression type
NamespaceAccess
};
/**
* @param firstContext should be true for a context that has no parent. Such a context will never be a function-call context.
* @param text the text to analyze. It usually is the text in the range starting at the beginning of the context, and ending at the position where completion should start
* @warning The du-chain must be unlocked when this is called
* @param knownArgumentExpressions has no effect when firstContext is set
* @param line Optional line that will be used to filter the macros
* */
CodeCompletionContext(KDevelop::DUContextPointer context, const QString& text, const QString& followingText, const KDevelop::CursorInRevision& position, int depth = 0, const QStringList& knownArgumentExpressions = QStringList(), int line = -1 );
~CodeCompletionContext();
/**In the case of recursive argument-hints, there may be a chain of parent-contexts, each for the higher argument-matching
* The parentContext() should always have the access-operation FunctionCallAccess.
* When a completion-list is computed, the members of the list can be highlighted that match the corresponding parentContext()->functions() function-argument, or parentContext()->additionalMatchTypes()
* */
CodeCompletionContext* parentContext() const;
///@return the used access-operation
AccessType accessType() const;
///@return the list of IndexedTypes that this CodeCompletionContext expects
QList<IndexedType> matchTypes();
/**
* When the access-operation is a MemberAccess or ArrowMemberAccess, this
* is the container that completion should happen in
* (the code-completion should list its non-static content).
*
* When memberAccessOperation is StaticMemberChoose, the code-completion
* should list all static members of this container.
*
* When memberAccessOperation is MemberChoose, it should be treated equivalently to MemberAccess.
*
* The type does not respect the member-access-operation, so
* the code-completion may check whether the arrow-access was used correctly
* and maybe do automatic correction.
* @return the type of the container that should be completed in.
* */
ExpressionEvaluationResult memberAccessContainer() const;
/**
* Returns the internal context of memberAccessContainer, if any.
*
* When memberAccessOperation is StaticMemberChoose, this returns all
* fitting namespace-contexts.
* *DUChain must be locked*
* */
QSet<DUContext*> memberAccessContainers() const;
/**
* When memberAccessOperation is FunctionCallAccess,
* this returns all functions available for matching, together with the argument-number that should be matched.
*
* Operators are treated as functions, but there is special-cases that need to be treated, especially operator=(..), because that operator competes with normal type-conversion.
*
* To also respect builtin operators, the types returned by additionalMatchTypes() must be respected.
* */
const FunctionList& functions() const;
/// @return of the function name for this context. Also works for operators.
QString functionName() const;
/**
* When memberAccessOperation is IncludeListAccess, then this contains all the files to be listed.
* */
QList<KDevelop::IncludeItem> includeItems() const;
int pointerConversions() const;
QString followingText() const;
void setFollowingText(QString str);
bool isConstructorInitialization();
///If this is a function call context, this returns the arguments to the function that are already known
QList<ExpressionEvaluationResult> knownArgumentTypes() const;
///Returns position of the argument being matched
int matchPosition() const;
#ifndef TEST_COMPLETION
private:
#endif
enum OnlyShow {
ShowAll,
ShowIntegralConstants, // compile-time integral constants and related items (scopes, ...)
ShowTypes,
ShowSignals,
ShowSlots,
ShowVariables,
ShowImplementationHelpers
};
#ifdef TEST_COMPLETION
OnlyShow onlyShow() { return m_onlyShow; };
private:
#endif
///Preprocess m_text (replace macros with their body etc.)
void preprocessText(int line);
///looks at @param str to determine current context
///*DUChain must be locked*
AccessType findAccessType(const QString &str) const;
///Get local class from m_duContext, if available
///*DUChain must be locked*
DUContextPointer findLocalClass() const;
///Find if this context should limit completions to certain kinds
///*DUChain must be locked*
OnlyShow findOnlyShow(const QString &accessStr) const;
///Get the types for m_knownArgumentExpressions
///*DUChain must be locked*
QList<ExpressionEvaluationResult> getKnownArgumentTypes() const;
///Looks in m_text to find @param expression, @param expressionPrefix,
///and whether the expression @param istypeprefix
///*DUChain must be locked*
void findExpressionAndPrefix(QString &expression, QString &expressionPrefix, bool &isTypePrefix) const;
///Create and return a parent context for the given @param expressionPrefix
KSharedPtr<KDevelop::CodeCompletionContext> getParentContext(const QString &expressionPrefix) const;
///Evaluate m_expression
ExpressionEvaluationResult evaluateExpression() const;
///Remove unary operators from the end of m_text, setting m_pointerConversionsBeforeMatching accordingly
void skipUnaryOperators(QString &str, int &pointerConversions) const;
///test if the context is valid for its accessType
bool testContextValidity(const QString &expressionPrefix, const QString &accessStr) const;
/**
* Specialized processing for access types
* *DUChain must be locked for these functions*
**/
void processArrowMemberAccess();
void processFunctionCallAccess();
void processAllMemberAccesses();
///Whether or not this context should add parent items
bool shouldAddParentItems(bool fullCompletion);
/**
* Item creation functions for various completion types
**/
///*DUChain must be locked*
QList<CompletionTreeItemPointer> keywordCompletionItems();
QList<CompletionTreeItemPointer> memberAccessCompletionItems(const bool& shouldAbort);
QList<CompletionTreeItemPointer> returnAccessCompletionItems();
QList<CompletionTreeItemPointer> caseAccessCompletionItems();
QList<CompletionTreeItemPointer> templateAccessCompletionItems();
QList<CompletionTreeItemPointer> functionAccessCompletionItems(bool fullCompletion);
QList<CompletionTreeItemPointer> binaryFunctionAccessCompletionItems(bool fullCompletion);
///*DUChain must _not_ be locked*
QList<CompletionTreeItemPointer> commonFunctionAccessCompletionItems(bool fullCompletion);
QList<CompletionTreeItemPointer> includeListAccessCompletionItems(const bool& shouldAbort);
QList<CompletionTreeItemPointer> signalSlotAccessCompletionItems();
///Computes the completion-items for the case that no special kind of access is used(just a list of all suitable items is needed)
QList<CompletionTreeItemPointer> standardAccessCompletionItems();
QList<CompletionTreeItemPointer> getImplementationHelpers();
QList<CompletionTreeItemPointer> getImplementationHelpersInternal(const QualifiedIdentifier& minimumScope, DUContext* context);
///If @param forDecl is an instance of a class, find declarations in that class which match @param matchTypes
///@returns the list of matching declarations and whether or not you need the arrow operator (->) to access them
QList<DeclAccessPair> getLookaheadMatches(Declaration* forDecl, const QList<IndexedType>& matchTypes) const;
void addLookaheadMatches(const QList<CompletionTreeItemPointer> items);
///For a given @param container, find members which may potentially be used for lookahead matching
///@param isPointer specifies whether the container should be accessed with operator->
///@returns a list of declarations paired with whether or not they use "operator->"
///Note that a non-pointer container may declare an operator-> (ie, smart pointer)
QList<DeclAccessPair> containedDeclarationsForLookahead(Declaration* decl, TopDUContext* top, bool isPointer) const;
///*DUChain must be locked*
bool filterDeclaration(Declaration* decl, DUContext* declarationContext = 0, bool dynamic = true) const;
///*DUChain must be locked*
bool filterDeclaration(ClassMemberDeclaration* decl, DUContext* declarationContext = 0) const;
/// Request a replace of the member-access type at the current cursor position from "oldAccess"
/// to "newAccess", for example from "->" to "."
/// The actual replacement is delayed into the foreground thread.
void replaceCurrentAccess(const QString& oldAccess, const QString& newAccess);
///Creates the group and adds it to m_storedUngroupedItems if items is not empty
void eventuallyAddGroup(QString name, int priority, QList< KSharedPtr< KDevelop::CompletionTreeItem > > items);
///@param type The type of the argument the items are matched to.
///*DUChain must be locked*
void addSpecialItemsForArgumentType(AbstractType::Ptr type);
///Returns whether the declaration is directly visible from within the current context
bool visibleFromWithin(Declaration* decl, DUContext* currentContext) const;
///Returns whether the declaration can be considered an integral constant
///@param acceptHelperItems whether we check for filtering (true) or for marking match quality (false)
bool isIntegralConstant(Declaration* decl, bool acceptHelperItems) const;
///Returns whether the end of m_text is a valid completion-position
bool isValidPosition();
///Returns whether this is a valid context for implementation helpers
bool isImplementationHelperValid() const;
/**
* Group adding functions
* *DUChain must be locked for these functions*
**/
void addOverridableItems();
void addImplementationHelpers();
void addCPPBuiltin();
/**
* Specialized completion functions, if these completion types are
* valid, no need to continue searching for information about this context
* *DUChain must be locked for these functions*
**/
///Handle SIGNAL/SLOT in connect/disconnect, \returns true if valid
bool doSignalSlotCompletion();
///Handle include path completion, \returns true if valid
bool doIncludeCompletion();
///Handle code-completion for constructor-initializers, \returns true if valid
bool doConstructorCompletion();
QList<DeclarationDepthPair> namespaceItems(KDevelop::DUContext* duContext, const KDevelop::CursorInRevision& position, bool global,
const QSet<KDevelop::DUContext*>& skipContexts = QSet<KDevelop::DUContext*>()) const;
AccessType m_accessType;
QString m_expression;
QString m_followingText;
QString m_operator; //If this completion-context ends with a binary operator, this is the operator
ExpressionEvaluationResult m_expressionResult;
//Here known argument-expressions and their types, that may have come from sub-contexts, are stored
QStringList m_knownArgumentExpressions;
QList<ExpressionEvaluationResult> m_knownArgumentTypes;
QString m_functionName;
QList<Function> m_matchingFunctionOverloads;
//If a signal/slot access is performed, and a slot is being connected to a signal, this contains the identifier and the signature
Identifier m_connectedSignalIdentifier;
QByteArray m_connectedSignalNormalizedSignature;
IndexedDeclaration m_connectedSignal;
//true if constructor completion is performed
bool m_isConstructorCompletion;
//include completion items for include completion
QList<KDevelop::IncludeItem> m_includeItems;
//0 = No conversion, +1, +2, .. = increase pointer level = &, -1, -2, .. = decrease pointer level = *
int m_pointerConversionsBeforeMatching;
QList<KDevelop::CompletionTreeElementPointer> m_storedUngroupedItems;
//A specific completion item type to show, or ShowAll, see enum OnlyShow
OnlyShow m_onlyShow;
//Expression is set to the type part in something like: {type}{varname}{initialization}
bool m_expressionIsTypePrefix;
bool m_doAccessFiltering;
DUContextPointer m_localClass;
QList<IndexedType> m_cachedMatchTypes;
/// Maps container declaration to cached return value of getLookaheadMatches
/// This is useful, as otherwise we'd repeat the same stuff for every variable
/// with the same type accessible from the current scope
mutable QHash<Declaration*, QList<DeclAccessPair> > m_lookaheadMatchesCache;
friend class ImplementationHelperItem;
};
}
#endif