mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 11:22:55 +00:00
361 lines
17 KiB
C++
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
|