work save
This commit is contained in:
parent
ea77b45661
commit
9066bc4897
|
@ -205,11 +205,11 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
return findStatementOf(fileName,phrase,findAndScanBlockAt(fileName,line));
|
return findStatementOf(fileName,phrase,findAndScanBlockAt(fileName,line));
|
||||||
}
|
}
|
||||||
|
|
||||||
PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentClass, PStatement ¤tClassType, bool force)
|
PStatement CppParser::findStatementOf(const QString &fileName, const QString &phrase, PStatement currentScope, PStatement &parentScopeType, bool force)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
PStatement result;
|
PStatement result;
|
||||||
currentClassType = currentClass;
|
parentScopeType = currentScope;
|
||||||
if (mParsing && !force)
|
if (mParsing && !force)
|
||||||
return PStatement();
|
return PStatement();
|
||||||
|
|
||||||
|
@ -249,10 +249,10 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
return PStatement();
|
return PStatement();
|
||||||
} else {
|
} else {
|
||||||
//unqualified name
|
//unqualified name
|
||||||
currentClassType = currentClass;
|
parentScopeType = currentScope;
|
||||||
remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName);
|
remainder = splitPhrase(remainder,nextScopeWord,operatorToken,memberName);
|
||||||
if (currentClass && (currentClass->kind == StatementKind::skNamespace)) {
|
if (currentScope && (currentScope->kind == StatementKind::skNamespace)) {
|
||||||
PStatementList namespaceList = mNamespaces.value(currentClass->fullName);
|
PStatementList namespaceList = mNamespaces.value(currentScope->fullName);
|
||||||
if (!namespaceList || namespaceList->isEmpty())
|
if (!namespaceList || namespaceList->isEmpty())
|
||||||
return PStatement();
|
return PStatement();
|
||||||
for (PStatement currentNamespace:*namespaceList){
|
for (PStatement currentNamespace:*namespaceList){
|
||||||
|
@ -261,15 +261,15 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
statement = findStatementStartingFrom(fileName,nextScopeWord,currentClassType,force);
|
statement = findStatementStartingFrom(fileName,nextScopeWord,parentScopeType,force);
|
||||||
}
|
}
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return PStatement();
|
return PStatement();
|
||||||
}
|
}
|
||||||
currentClassType = currentClass;
|
parentScopeType = currentScope;
|
||||||
|
|
||||||
if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
|
if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
|
||||||
PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
|
PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, parentScopeType);
|
||||||
if (typeStatement)
|
if (typeStatement)
|
||||||
statement = typeStatement;
|
statement = typeStatement;
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
if ((statement->kind == StatementKind::skAlias) &&
|
if ((statement->kind == StatementKind::skAlias) &&
|
||||||
(phrase!=statement->type)) {
|
(phrase!=statement->type)) {
|
||||||
statement = findStatementOf(fileName, statement->type,
|
statement = findStatementOf(fileName, statement->type,
|
||||||
currentClass, currentClassType, force);
|
currentScope, parentScopeType, force);
|
||||||
if (!statement)
|
if (!statement)
|
||||||
return PStatement();
|
return PStatement();
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isSTLContainerFunctions)
|
if (!isSTLContainerFunctions)
|
||||||
typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
|
typeStatement = findTypeDefinitionOf(fileName,statement->type, parentScopeType);
|
||||||
|
|
||||||
//it's stl smart pointer
|
//it's stl smart pointer
|
||||||
if ((typeStatement)
|
if ((typeStatement)
|
||||||
|
@ -344,10 +344,10 @@ PStatement CppParser::findStatementOf(const QString &fileName, const QString &ph
|
||||||
if (!memberStatement)
|
if (!memberStatement)
|
||||||
return PStatement();
|
return PStatement();
|
||||||
|
|
||||||
currentClassType=statement;
|
parentScopeType=statement;
|
||||||
statement = memberStatement;
|
statement = memberStatement;
|
||||||
if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
|
if (!memberName.isEmpty() && (statement->kind == StatementKind::skTypedef)) {
|
||||||
PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, currentClassType);
|
PStatement typeStatement = findTypeDefinitionOf(fileName,statement->type, parentScopeType);
|
||||||
if (typeStatement)
|
if (typeStatement)
|
||||||
statement = typeStatement;
|
statement = typeStatement;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,8 +42,8 @@ public:
|
||||||
int line);
|
int line);
|
||||||
PStatement findStatementOf(const QString& fileName,
|
PStatement findStatementOf(const QString& fileName,
|
||||||
const QString& phrase,
|
const QString& phrase,
|
||||||
PStatement currentClass,
|
PStatement currentScope,
|
||||||
PStatement& currentClassType,
|
PStatement& parentScopeType,
|
||||||
bool force = false);
|
bool force = false);
|
||||||
PStatement findStatementOf(const QString& fileName,
|
PStatement findStatementOf(const QString& fileName,
|
||||||
const QString& phrase,
|
const QString& phrase,
|
||||||
|
|
|
@ -9,6 +9,7 @@ QStringList CppDirectives;
|
||||||
QStringList JavadocTags;
|
QStringList JavadocTags;
|
||||||
QMap<QString,SkipType> CppKeywords;
|
QMap<QString,SkipType> CppKeywords;
|
||||||
QSet<QString> CppTypeKeywords;
|
QSet<QString> CppTypeKeywords;
|
||||||
|
QSet<QString> CKeywords;
|
||||||
QSet<QString> STLPointers;
|
QSet<QString> STLPointers;
|
||||||
QSet<QString> STLContainers;
|
QSet<QString> STLContainers;
|
||||||
QSet<QString> STLElementMethods;
|
QSet<QString> STLElementMethods;
|
||||||
|
@ -181,7 +182,41 @@ void initParser()
|
||||||
// nullptr is value
|
// nullptr is value
|
||||||
CppKeywords.insert("nullptr",SkipType::skNone);
|
CppKeywords.insert("nullptr",SkipType::skNone);
|
||||||
|
|
||||||
|
//C Keywords
|
||||||
|
CKeywords.insert("auto");
|
||||||
|
CKeywords.insert("break");
|
||||||
|
CKeywords.insert("case");
|
||||||
|
CKeywords.insert("char");
|
||||||
|
CKeywords.insert("const");
|
||||||
|
CKeywords.insert("continue");
|
||||||
|
CKeywords.insert("default");
|
||||||
|
CKeywords.insert("do");
|
||||||
|
CKeywords.insert("double");
|
||||||
|
CKeywords.insert("else");
|
||||||
|
CKeywords.insert("enum");
|
||||||
|
CKeywords.insert("extern");
|
||||||
|
CKeywords.insert("float");
|
||||||
|
CKeywords.insert("for");
|
||||||
|
CKeywords.insert("goto");
|
||||||
|
CKeywords.insert("if");
|
||||||
|
CKeywords.insert("inline");
|
||||||
|
CKeywords.insert("int");
|
||||||
|
CKeywords.insert("long");
|
||||||
|
CKeywords.insert("register");
|
||||||
|
CKeywords.insert("restrict");
|
||||||
|
CKeywords.insert("return");
|
||||||
|
CKeywords.insert("short");
|
||||||
|
CKeywords.insert("signed");
|
||||||
|
CKeywords.insert("sizeof");
|
||||||
|
CKeywords.insert("static");
|
||||||
|
CKeywords.insert("struct");
|
||||||
|
CKeywords.insert("switch");
|
||||||
|
CKeywords.insert("typedef");
|
||||||
|
CKeywords.insert("union");
|
||||||
|
CKeywords.insert("unsigned");
|
||||||
|
CKeywords.insert("void");
|
||||||
|
CKeywords.insert("volatile");
|
||||||
|
CKeywords.insert("while");
|
||||||
|
|
||||||
//STL Containers
|
//STL Containers
|
||||||
STLContainers.insert("std::array");
|
STLContainers.insert("std::array");
|
||||||
|
@ -426,3 +461,33 @@ void CppScopes::clear()
|
||||||
{
|
{
|
||||||
mScopes.clear();
|
mScopes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MemberOperatorType getOperatorType(const QString &phrase, int index)
|
||||||
|
{
|
||||||
|
MemberOperatorType result=MemberOperatorType::otOther;
|
||||||
|
if (index>=phrase.length())
|
||||||
|
return MemberOperatorType::otOther;
|
||||||
|
if (phrase[index] == '.')
|
||||||
|
return MemberOperatorType::otDot;
|
||||||
|
if (index+1>=phrase.length())
|
||||||
|
return MemberOperatorType::otOther;
|
||||||
|
if ((phrase[index] == '-') && (phrase[index+1] == '>'))
|
||||||
|
return MemberOperatorType::otArrow;
|
||||||
|
if ((phrase[index] == ':') && (phrase[index+1] == ':'))
|
||||||
|
return MemberOperatorType::otDColon;
|
||||||
|
return MemberOperatorType::otOther;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isScopeTypeKind(StatementKind kind)
|
||||||
|
{
|
||||||
|
switch(kind) {
|
||||||
|
case StatementKind::skClass:
|
||||||
|
case StatementKind::skNamespace:
|
||||||
|
case StatementKind::skFunction:
|
||||||
|
case StatementKind::skConstructor:
|
||||||
|
case StatementKind::skDestructor:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -184,6 +184,7 @@ using PFileIncludes = std::shared_ptr<FileIncludes>;
|
||||||
extern QStringList CppDirectives;
|
extern QStringList CppDirectives;
|
||||||
extern QStringList JavadocTags;
|
extern QStringList JavadocTags;
|
||||||
extern QMap<QString,SkipType> CppKeywords;
|
extern QMap<QString,SkipType> CppKeywords;
|
||||||
|
extern QSet<QString> CKeywords;
|
||||||
extern QSet<QString> CppTypeKeywords;
|
extern QSet<QString> CppTypeKeywords;
|
||||||
extern QSet<QString> STLPointers;
|
extern QSet<QString> STLPointers;
|
||||||
extern QSet<QString> STLContainers;
|
extern QSet<QString> STLContainers;
|
||||||
|
@ -201,5 +202,7 @@ bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePat
|
||||||
bool isHfile(const QString filename);
|
bool isHfile(const QString filename);
|
||||||
bool isCfile(const QString filename);
|
bool isCfile(const QString filename);
|
||||||
bool isKeyword(const QString& word);
|
bool isKeyword(const QString& word);
|
||||||
|
bool isScopeTypeKind(StatementKind kind);
|
||||||
|
MemberOperatorType getOperatorType(const QString& phrase, int index);
|
||||||
|
|
||||||
#endif // PARSER_UTILS_H
|
#endif // PARSER_UTILS_H
|
||||||
|
|
|
@ -12,6 +12,16 @@ CodeCompletionView::CodeCompletionView(QWidget *parent) :
|
||||||
setLayout(new QVBoxLayout());
|
setLayout(new QVBoxLayout());
|
||||||
layout()->addWidget(mListView);
|
layout()->addWidget(mListView);
|
||||||
layout()->setMargin(0);
|
layout()->setMargin(0);
|
||||||
|
|
||||||
|
mShowKeywords=true;
|
||||||
|
mUseCppKeyword=true;
|
||||||
|
|
||||||
|
mEnabled = true;
|
||||||
|
mOnlyGlobals = false;
|
||||||
|
mShowCount = 1000;
|
||||||
|
mShowCodeIns = true;
|
||||||
|
|
||||||
|
mIgnoreCase = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeCompletionView::~CodeCompletionView()
|
CodeCompletionView::~CodeCompletionView()
|
||||||
|
@ -24,6 +34,78 @@ void CodeCompletionView::setKeypressedCallback(const KeyPressedCallback &newKeyp
|
||||||
mListView->setKeypressedCallback(newKeypressedCallback);
|
mListView->setKeypressedCallback(newKeypressedCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeCompletionView::prepareSearch(const QString &phrase, const QString &filename, int line)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mMutex);
|
||||||
|
if (!mEnabled)
|
||||||
|
return;
|
||||||
|
mPhrase = phrase;
|
||||||
|
//Screen.Cursor := crHourglass;
|
||||||
|
QCursor oldCursor = cursor();
|
||||||
|
setCursor(Qt::CursorShape::WaitCursor);
|
||||||
|
|
||||||
|
mIncludedFiles = mParser->getFileIncludes(filename);
|
||||||
|
getCompletionFor(filename,phrase,line);
|
||||||
|
|
||||||
|
//todo: notify model
|
||||||
|
//CodeComplForm.lbCompletion.Font.Size := FontSize;
|
||||||
|
//CodeComplForm.lbCompletion.ItemHeight := CodeComplForm.lbCompletion.Canvas.TextHeight('F')+6;
|
||||||
|
// Round(2 * FontSize);
|
||||||
|
//CodeComplForm.Update;
|
||||||
|
setCursor(oldCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodeCompletionView::search(const QString &phrase, const QString &filename, bool autoHideOnSingleResult)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mMutex);
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
mPhrase = phrase;
|
||||||
|
|
||||||
|
if (phrase.isEmpty()) {
|
||||||
|
hide();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!mEnabled) {
|
||||||
|
hide();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QCursor oldCursor = cursor();
|
||||||
|
setCursor(Qt::CursorShape::WaitCursor);
|
||||||
|
|
||||||
|
// Sort here by member
|
||||||
|
int i = mParser->findLastOperator(phrase);
|
||||||
|
while ((i>=0) && (i<phrase.length()) && (
|
||||||
|
phrase[i] == '.'
|
||||||
|
|| phrase[i] == ':'
|
||||||
|
|| phrase[i] == '-'
|
||||||
|
|| phrase[i] == '>'))
|
||||||
|
i++;
|
||||||
|
|
||||||
|
QString symbol = phrase.mid(i);
|
||||||
|
// filter fFullCompletionStatementList to fCompletionStatementList
|
||||||
|
filterList(symbol);
|
||||||
|
|
||||||
|
|
||||||
|
if (!mCompletionStatementList.isEmpty()) {
|
||||||
|
//todo:update model
|
||||||
|
|
||||||
|
setCursor(oldCursor);
|
||||||
|
// if only one suggestion, and is exactly the symbol to search, hide the frame (the search is over)
|
||||||
|
// if only one suggestion and auto hide , don't show the frame
|
||||||
|
if(mCompletionStatementList.count() == 1)
|
||||||
|
if (autoHideOnSingleResult
|
||||||
|
|| (symbol == mCompletionStatementList.front()->command)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//todo:update(clear) the model
|
||||||
|
setCursor(oldCursor);
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &fileName, int line)
|
void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &fileName, int line)
|
||||||
{
|
{
|
||||||
if (scopeStatement && !isIncluded(scopeStatement->fileName)
|
if (scopeStatement && !isIncluded(scopeStatement->fileName)
|
||||||
|
@ -64,6 +146,8 @@ void CodeCompletionView::addChildren(PStatement scopeStatement, const QString &f
|
||||||
|
|
||||||
void CodeCompletionView::addStatement(PStatement statement, const QString &fileName, int line)
|
void CodeCompletionView::addStatement(PStatement statement, const QString &fileName, int line)
|
||||||
{
|
{
|
||||||
|
if (mAddedStatements.contains(statement->command))
|
||||||
|
return;
|
||||||
if ((line!=-1)
|
if ((line!=-1)
|
||||||
&& (line < statement->line)
|
&& (line < statement->line)
|
||||||
&& (fileName == statement->fileName))
|
&& (fileName == statement->fileName))
|
||||||
|
@ -211,24 +295,24 @@ void CodeCompletionView::filterList(const QString &member)
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
QList<PStatement> tmpList;
|
mCompletionStatementList.clear();
|
||||||
if (!member.isEmpty()) { // filter
|
if (!member.isEmpty()) { // filter
|
||||||
tmpList.reserve(mFullCompletionStatementList.size());
|
mCompletionStatementList.reserve(mFullCompletionStatementList.size());
|
||||||
for (PStatement statement:mFullCompletionStatementList) {
|
for (PStatement statement:mFullCompletionStatementList) {
|
||||||
Qt::CaseSensitivity cs = (mIgnoreCase?
|
Qt::CaseSensitivity cs = (mIgnoreCase?
|
||||||
Qt::CaseInsensitive:
|
Qt::CaseInsensitive:
|
||||||
Qt::CaseSensitive);
|
Qt::CaseSensitive);
|
||||||
if (statement->command.startsWith(member, cs))
|
if (statement->command.startsWith(member, cs))
|
||||||
tmpList.append(statement);
|
mCompletionStatementList.append(statement);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
tmpList = mCompletionStatementList;
|
mCompletionStatementList.append(mFullCompletionStatementList);
|
||||||
if (mRecordUsage) {
|
if (mRecordUsage) {
|
||||||
int topCount = 0;
|
int topCount = 0;
|
||||||
int secondCount = 0;
|
int secondCount = 0;
|
||||||
int thirdCount = 0;
|
int thirdCount = 0;
|
||||||
int usageCount;
|
int usageCount;
|
||||||
for (PStatement statement:tmpList) {
|
for (PStatement statement:mCompletionStatementList) {
|
||||||
if (statement->usageCount == 0) {
|
if (statement->usageCount == 0) {
|
||||||
usageCount = mSymbolUsage.value(statement->fullName,0);
|
usageCount = mSymbolUsage.value(statement->fullName,0);
|
||||||
if (usageCount == 0)
|
if (usageCount == 0)
|
||||||
|
@ -251,7 +335,7 @@ void CodeCompletionView::filterList(const QString &member)
|
||||||
thirdCount = usageCount;
|
thirdCount = usageCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (PStatement statement:tmpList) {
|
for (PStatement statement:mCompletionStatementList) {
|
||||||
if (statement->usageCount == 0) {
|
if (statement->usageCount == 0) {
|
||||||
statement->freqTop = 0;
|
statement->freqTop = 0;
|
||||||
} else if (statement->usageCount == topCount) {
|
} else if (statement->usageCount == topCount) {
|
||||||
|
@ -263,16 +347,338 @@ void CodeCompletionView::filterList(const QString &member)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mSortByScope) {
|
if (mSortByScope) {
|
||||||
std::sort(tmpList.begin(),tmpList.end(),sortByScopeWithUsageComparator);
|
std::sort(mCompletionStatementList.begin(),
|
||||||
|
mCompletionStatementList.end(),
|
||||||
|
sortByScopeWithUsageComparator);
|
||||||
} else {
|
} else {
|
||||||
std::sort(tmpList.begin(),tmpList.end(),sortWithUsageComparator);
|
std::sort(mCompletionStatementList.begin(),
|
||||||
|
mCompletionStatementList.end(),
|
||||||
|
sortWithUsageComparator);
|
||||||
}
|
}
|
||||||
} else if (mSortByScope) {
|
} else if (mSortByScope) {
|
||||||
std::sort(tmpList.begin(),tmpList.end(),sortByScopeComparator);
|
std::sort(mCompletionStatementList.begin(),
|
||||||
|
mCompletionStatementList.end(),
|
||||||
|
sortByScopeComparator);
|
||||||
} else {
|
} else {
|
||||||
std::sort(tmpList.begin(),tmpList.end(),defaultComparator);
|
std::sort(mCompletionStatementList.begin(),
|
||||||
|
mCompletionStatementList.end(),
|
||||||
|
defaultComparator);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCompletionView::getCompletionFor(const QString &fileName, const QString &phrase, int line)
|
||||||
|
{
|
||||||
|
if(!mParser)
|
||||||
|
return;
|
||||||
|
if (!mParser->enabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!mParser->freeze())
|
||||||
|
return;
|
||||||
|
{
|
||||||
|
auto action = finally([this]{
|
||||||
|
mParser->unFreeze();
|
||||||
|
});
|
||||||
|
|
||||||
|
//C++ preprocessor directives
|
||||||
|
if (phrase.startsWith('#')) {
|
||||||
|
if (mShowKeywords) {
|
||||||
|
for (QString keyword:CppDirectives) {
|
||||||
|
PStatement statement = std::make_shared<Statement>();
|
||||||
|
statement->command = keyword;
|
||||||
|
statement->kind = StatementKind::skPreprocessor;
|
||||||
|
statement->fullName = keyword;
|
||||||
|
mFullCompletionStatementList.append(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//docstring tags (javadoc style)
|
||||||
|
if (phrase.startsWith('@')) {
|
||||||
|
if (mShowKeywords) {
|
||||||
|
for (QString keyword:JavadocTags) {
|
||||||
|
PStatement statement = std::make_shared<Statement>();
|
||||||
|
statement->command = keyword;
|
||||||
|
statement->kind = StatementKind::skKeyword;
|
||||||
|
statement->fullName = keyword;
|
||||||
|
mFullCompletionStatementList.append(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Pulling off the same trick as in TCppParser.FindStatementOf, but ignore everything after last operator
|
||||||
|
int i = mParser->findLastOperator(phrase);
|
||||||
|
if (i < 0 ) { // don't have any scope prefix
|
||||||
|
|
||||||
|
if (mShowCodeIns) {
|
||||||
|
//add custom code templates
|
||||||
|
for (PCodeIns codeIn:mCodeInsList) {
|
||||||
|
PStatement statement = std::make_shared<Statement>();
|
||||||
|
statement->command = codeIn->prefix;
|
||||||
|
statement->kind = StatementKind::skUserCodeIn;
|
||||||
|
statement->fullName = codeIn->prefix;
|
||||||
|
mFullCompletionStatementList.append(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mShowKeywords) {
|
||||||
|
//add keywords
|
||||||
|
if (mUseCppKeyword) {
|
||||||
|
for (QString keyword:CppKeywords.keys()) {
|
||||||
|
PStatement statement = std::make_shared<Statement>();
|
||||||
|
statement->command = keyword;
|
||||||
|
statement->kind = StatementKind::skKeyword;
|
||||||
|
statement->fullName = keyword;
|
||||||
|
mFullCompletionStatementList.append(statement);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (QString keyword:CKeywords) {
|
||||||
|
PStatement statement = std::make_shared<Statement>();
|
||||||
|
statement->command = keyword;
|
||||||
|
statement->kind = StatementKind::skKeyword;
|
||||||
|
statement->fullName = keyword;
|
||||||
|
mFullCompletionStatementList.append(statement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PStatement scopeStatement = mCurrentStatement;
|
||||||
|
// repeat until reach global
|
||||||
|
while (scopeStatement) {
|
||||||
|
//add members of current scope that not added before
|
||||||
|
if (scopeStatement->kind == StatementKind::skClass) {
|
||||||
|
addChildren(scopeStatement, fileName, -1);
|
||||||
|
} else {
|
||||||
|
addChildren(scopeStatement, fileName, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add members of all usings (in current scope ) and not added before
|
||||||
|
for (QString namespaceName:scopeStatement->usingList) {
|
||||||
|
PStatementList namespaceStatementsList =
|
||||||
|
mParser->findNamespace(namespaceName);
|
||||||
|
if (!namespaceStatementsList)
|
||||||
|
continue;
|
||||||
|
for (PStatement namespaceStatement:*namespaceStatementsList) {
|
||||||
|
addChildren(namespaceStatement, fileName, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scopeStatement=scopeStatement->parentScope.lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// add all global members and not added before
|
||||||
|
addChildren(nullptr, fileName, line);
|
||||||
|
|
||||||
|
// add members of all fusings
|
||||||
|
mUsings = mParser->getFileUsings(fileName);
|
||||||
|
for (QString namespaceName:mUsings) {
|
||||||
|
PStatementList namespaceStatementsList =
|
||||||
|
mParser->findNamespace(namespaceName);
|
||||||
|
if (!namespaceStatementsList)
|
||||||
|
continue;
|
||||||
|
for (PStatement namespaceStatement:*namespaceStatementsList) {
|
||||||
|
addChildren(namespaceStatement, fileName, line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else { //we are in some statement's scope
|
||||||
|
MemberOperatorType opType=getOperatorType(phrase,i);
|
||||||
|
QString scopeName = phrase.mid(0,i);
|
||||||
|
if (opType == MemberOperatorType::otDColon) {
|
||||||
|
if (scopeName.isEmpty()) {
|
||||||
|
// start with '::', we only find in global
|
||||||
|
// add all global members and not added before
|
||||||
|
addChildren(nullptr, fileName, line);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
//assume the scope its a namespace
|
||||||
|
PStatementList namespaceStatementsList =
|
||||||
|
mParser->findNamespace(scopeName);
|
||||||
|
if (namespaceStatementsList) {
|
||||||
|
for (PStatement namespaceStatement:*namespaceStatementsList) {
|
||||||
|
addChildren(namespaceStatement, fileName, line);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//namespace not found let's go on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PStatement parentTypeStatement;
|
||||||
|
PStatement statement = mParser->findStatementOf(
|
||||||
|
fileName, scopeName,mCurrentStatement,parentTypeStatement);
|
||||||
|
if (!statement)
|
||||||
|
return;
|
||||||
|
// find the most inner scope statement that has a name (not a block)
|
||||||
|
PStatement scopeTypeStatement = mCurrentStatement;
|
||||||
|
while (scopeTypeStatement && !isScopeTypeKind(scopeTypeStatement->kind)) {
|
||||||
|
scopeTypeStatement = scopeTypeStatement->parentScope.lock();
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
(opType == MemberOperatorType::otArrow
|
||||||
|
|| opType == MemberOperatorType::otDot)
|
||||||
|
&& (
|
||||||
|
statement->kind == StatementKind::skVariable
|
||||||
|
|| statement->kind == StatementKind::skParameter
|
||||||
|
|| statement->kind == StatementKind::skFunction)
|
||||||
|
) {
|
||||||
|
// Get type statement of current (scope) statement
|
||||||
|
PStatement classTypeStatement;
|
||||||
|
PStatement parentScope = statement->parentScope.lock();
|
||||||
|
if ((statement->kind == StatementKind::skFunction)
|
||||||
|
&& parentScope
|
||||||
|
&& STLContainers.contains(parentScope->fullName)
|
||||||
|
&& STLElementMethods.contains(statement->command)){
|
||||||
|
// it's an element method of STL container
|
||||||
|
// we must find the type in the template parameter
|
||||||
|
|
||||||
|
// get the function's owner variable's definition
|
||||||
|
int lastI = mParser->findLastOperator(scopeName);
|
||||||
|
QString lastScopeName = scopeName.mid(0,lastI);
|
||||||
|
PStatement lastScopeStatement =
|
||||||
|
mParser->findStatementOf(
|
||||||
|
fileName, lastScopeName,
|
||||||
|
mCurrentStatement,parentTypeStatement);
|
||||||
|
if (!lastScopeStatement)
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
QString typeName =
|
||||||
|
mParser->findFirstTemplateParamOf(
|
||||||
|
fileName,lastScopeStatement->type,
|
||||||
|
lastScopeStatement->parentScope.lock());
|
||||||
|
classTypeStatement = mParser->findTypeDefinitionOf(
|
||||||
|
fileName, typeName,
|
||||||
|
lastScopeStatement->parentScope.lock());
|
||||||
|
} else
|
||||||
|
classTypeStatement=mParser->findTypeDefinitionOf(
|
||||||
|
fileName, statement->type,parentTypeStatement);
|
||||||
|
|
||||||
|
if (!classTypeStatement)
|
||||||
|
return;
|
||||||
|
//is a smart pointer
|
||||||
|
if (STLPointers.contains(classTypeStatement->fullName)
|
||||||
|
&& (opType == MemberOperatorType::otArrow)) {
|
||||||
|
QString typeName= mParser->findFirstTemplateParamOf(
|
||||||
|
fileName,
|
||||||
|
statement->type,
|
||||||
|
parentScope);
|
||||||
|
classTypeStatement = mParser->findTypeDefinitionOf(
|
||||||
|
fileName,
|
||||||
|
typeName,
|
||||||
|
parentScope);
|
||||||
|
if (!classTypeStatement)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//is a stl container operator[]
|
||||||
|
if (STLContainers.contains(classTypeStatement->fullName)
|
||||||
|
&& scopeName.endsWith(']')) {
|
||||||
|
QString typeName= mParser->findFirstTemplateParamOf(
|
||||||
|
fileName,
|
||||||
|
statement->type,
|
||||||
|
parentScope);
|
||||||
|
classTypeStatement = mParser->findTypeDefinitionOf(
|
||||||
|
fileName,
|
||||||
|
typeName,
|
||||||
|
parentScope);
|
||||||
|
if (!classTypeStatement)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!isIncluded(classTypeStatement->fileName) &&
|
||||||
|
!isIncluded(classTypeStatement->definitionFileName))
|
||||||
|
return;
|
||||||
|
if ((classTypeStatement == scopeTypeStatement) || (statement->command == "this")) {
|
||||||
|
//we can use all members
|
||||||
|
addChildren(classTypeStatement,fileName,-1);
|
||||||
|
} else { // we can only use public members
|
||||||
|
const StatementMap& children = mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
|
if (children.isEmpty())
|
||||||
|
return;
|
||||||
|
for (PStatement childStatement:children) {
|
||||||
|
if ((childStatement->classScope==StatementClassScope::scsPublic)
|
||||||
|
&& !(
|
||||||
|
childStatement->kind == StatementKind::skConstructor
|
||||||
|
|| childStatement->kind == StatementKind::skDestructor)
|
||||||
|
&& !mAddedStatements.contains(childStatement->command)) {
|
||||||
|
addStatement(childStatement,fileName,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//todo friend
|
||||||
|
} else if ((opType == MemberOperatorType::otDColon)
|
||||||
|
&& (statement->kind == StatementKind::skEnumType)
|
||||||
|
&& (statement->kind == StatementKind::skEnumClassType)) {
|
||||||
|
//we can add all child enum definess
|
||||||
|
PStatement classTypeStatement = statement;
|
||||||
|
if (!isIncluded(classTypeStatement->fileName) &&
|
||||||
|
!isIncluded(classTypeStatement->definitionFileName))
|
||||||
|
return;
|
||||||
|
const StatementMap& children =
|
||||||
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
|
for (PStatement child:children) {
|
||||||
|
addStatement(child,fileName,line);
|
||||||
|
}
|
||||||
|
} else if ((opType == MemberOperatorType::otDColon)
|
||||||
|
&& (statement->kind == StatementKind::skClass)) {
|
||||||
|
PStatement classTypeStatement = statement;
|
||||||
|
if (!isIncluded(classTypeStatement->fileName) &&
|
||||||
|
!isIncluded(classTypeStatement->definitionFileName))
|
||||||
|
return;
|
||||||
|
if (classTypeStatement == scopeTypeStatement) {
|
||||||
|
//we can use all static members
|
||||||
|
const StatementMap& children =
|
||||||
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
|
for (PStatement childStatement: children) {
|
||||||
|
if (
|
||||||
|
(childStatement->isStatic)
|
||||||
|
|| (childStatement->kind == StatementKind::skTypedef
|
||||||
|
|| childStatement->kind == StatementKind::skClass
|
||||||
|
|| childStatement->kind == StatementKind::skEnum
|
||||||
|
|| childStatement->kind == StatementKind::skEnumClassType
|
||||||
|
|| childStatement->kind == StatementKind::skEnumType
|
||||||
|
)) {
|
||||||
|
addStatement(childStatement,fileName,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// we can only use public static members
|
||||||
|
const StatementMap& children =
|
||||||
|
mParser->statementList().childrenStatements(classTypeStatement);
|
||||||
|
for (PStatement childStatement: children) {
|
||||||
|
if (
|
||||||
|
(childStatement->isStatic)
|
||||||
|
|| (childStatement->kind == StatementKind::skTypedef
|
||||||
|
|| childStatement->kind == StatementKind::skClass
|
||||||
|
|| childStatement->kind == StatementKind::skEnum
|
||||||
|
|| childStatement->kind == StatementKind::skEnumClassType
|
||||||
|
|| childStatement->kind == StatementKind::skEnumType
|
||||||
|
)) {
|
||||||
|
if (childStatement->classScope == StatementClassScope::scsPublic)
|
||||||
|
addStatement(childStatement,fileName,-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//todo friend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CodeCompletionView::isIncluded(const QString &fileName)
|
||||||
|
{
|
||||||
|
return mIncludedFiles.contains(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CodeCompletionView::hideEvent(QHideEvent *event)
|
||||||
|
{
|
||||||
|
QMutexLocker locker(&mMutex);
|
||||||
|
mCompletionStatementList.clear();
|
||||||
|
mFullCompletionStatementList.clear();
|
||||||
|
mIncludedFiles.clear();
|
||||||
|
mUsings.clear();
|
||||||
|
mAddedStatements.clear();
|
||||||
|
QWidget::hideEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent)
|
CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent)
|
||||||
|
|
|
@ -31,6 +31,10 @@ public:
|
||||||
~CodeCompletionView();
|
~CodeCompletionView();
|
||||||
|
|
||||||
void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback);
|
void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback);
|
||||||
|
void prepareSearch(const QString& phrase, const QString& filename, int line);
|
||||||
|
bool search(const QString& phrase, const QString& filename,
|
||||||
|
bool autoHideOnSingleResult);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void addChildren(PStatement scopeStatement, const QString& fileName,
|
void addChildren(PStatement scopeStatement, const QString& fileName,
|
||||||
|
@ -52,10 +56,7 @@ private:
|
||||||
PStatement mCurrentStatement;
|
PStatement mCurrentStatement;
|
||||||
QSet<QString> mIncludedFiles;
|
QSet<QString> mIncludedFiles;
|
||||||
QSet<QString> mUsings;
|
QSet<QString> mUsings;
|
||||||
QString mIsIncludedCacheFileName;
|
|
||||||
bool mIsIncludedCacheResult;
|
|
||||||
QSet<QString> mAddedStatements;
|
QSet<QString> mAddedStatements;
|
||||||
bool mPreparing;
|
|
||||||
QString mPhrase;
|
QString mPhrase;
|
||||||
QHash<QString,int> mSymbolUsage;
|
QHash<QString,int> mSymbolUsage;
|
||||||
bool mRecordUsage;
|
bool mRecordUsage;
|
||||||
|
@ -63,9 +64,13 @@ private:
|
||||||
bool mShowCodeIns;
|
bool mShowCodeIns;
|
||||||
bool mIgnoreCase;
|
bool mIgnoreCase;
|
||||||
QRecursiveMutex mMutex;
|
QRecursiveMutex mMutex;
|
||||||
QString mParserSerialId;
|
|
||||||
bool mSortByScope;
|
bool mSortByScope;
|
||||||
bool mUseCppKeyword;
|
bool mUseCppKeyword;
|
||||||
|
|
||||||
|
|
||||||
|
// QWidget interface
|
||||||
|
protected:
|
||||||
|
void hideEvent(QHideEvent *event) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CODECOMPLETIONVIEW_H
|
#endif // CODECOMPLETIONVIEW_H
|
||||||
|
|
Loading…
Reference in New Issue