- enhancement: show completion tips for when define a function that already has a declaration.

- clean up code
This commit is contained in:
Roy Qu 2022-11-10 13:35:13 +08:00
parent 9072e752a0
commit eceba8b8f2
8 changed files with 268 additions and 75 deletions

View File

@ -14,6 +14,7 @@ Red Panda C++ Version 2.4
- fix: var assignment not correctly handled in code parser;
- fix: function args not correctly handled in code parser;
- fix: crash when alt+mouse drag selection
- enhancement: show completion tips for when define a function that already has a declaration.
Red Panda C++ Version 2.3

View File

@ -731,24 +731,28 @@ void Editor::keyPressEvent(QKeyEvent *event)
QString lastWord = getPreviousWordAtPositionForSuggestion(caretXY());
if (mParser && !lastWord.isEmpty()) {
if (CppTypeKeywords.contains(lastWord)) {
PStatement currentScope = mParser->findScopeStatement(mFilename,caretY());
while(currentScope && currentScope->kind==StatementKind::skBlock) {
currentScope = currentScope->parentScope.lock();
}
if (!currentScope || currentScope->kind == StatementKind::skNamespace) {
//may define a function
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion(lastWord,false,CodeCompletionType::FunctionWithoutDefinition);
handled=true;
return;
}
if (lastWord == "long" ||
lastWord == "short" ||
lastWord == "signed" ||
lastWord == "unsigned"
) {
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion(lastWord,false);
showCompletion(lastWord,false, CodeCompletionType::TypeKeywordComplex);
handled=true;
return;
}
PStatement currentScope = mParser->findScopeStatement(mFilename,caretY());
while(currentScope && currentScope->kind==StatementKind::skBlock) {
currentScope = currentScope->parentScope.lock();
}
if (!currentScope || currentScope->kind == StatementKind::skNamespace) {
return;
}
//last word is a type keyword, this is a var or param define, and dont show suggestion
return;
@ -762,12 +766,41 @@ void Editor::keyPressEvent(QKeyEvent *event)
|| kind == StatementKind::skEnumClassType
|| kind == StatementKind::skEnumType
|| kind == StatementKind::skTypedef) {
PStatement currentScope = mParser->findScopeStatement(mFilename,caretY());
while(currentScope && currentScope->kind==StatementKind::skBlock) {
currentScope = currentScope->parentScope.lock();
}
if (!currentScope || currentScope->kind == StatementKind::skNamespace) {
//may define a function
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion("",false,CodeCompletionType::FunctionWithoutDefinition);
handled=true;
return;
}
//last word is a typedef/class/struct, this is a var or param define, and dont show suggestion
return;
}
}
qDebug()<<"lalalala";
lastWord = getPreviousWordAtPositionForCompleteFunctionDefinition(caretXY());
qDebug()<<lastWord;
if (!lastWord.isEmpty()) {
PStatement currentScope = mParser->findScopeStatement(mFilename,caretY());
while(currentScope && currentScope->kind==StatementKind::skBlock) {
currentScope = currentScope->parentScope.lock();
}
if (!currentScope || currentScope->kind == StatementKind::skNamespace) {
//may define a function
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion("",false,CodeCompletionType::FunctionWithoutDefinition);
handled=true;
return;
}
}
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
handled=true;
return;
}
@ -779,7 +812,7 @@ void Editor::keyPressEvent(QKeyEvent *event)
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
mLastIdCharPressed++;
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
handled=true;
return;
}
@ -791,7 +824,7 @@ void Editor::keyPressEvent(QKeyEvent *event)
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
mLastIdCharPressed++;
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
handled=true;
return;
}
@ -1269,7 +1302,7 @@ void Editor::inputMethodEvent(QInputMethodEvent *event)
return;
}
}
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
return;
}
}
@ -2564,20 +2597,20 @@ bool Editor::handleCodeCompletion(QChar key)
switch(key.unicode()) {
case '.':
commandProcessor(QSynedit::EditCommand::ecChar, key);
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
return true;
case '>':
commandProcessor(QSynedit::EditCommand::ecChar, key);
if ((caretX() > 2) && (lineText().length() >= 2) &&
(lineText()[caretX() - 3] == '-'))
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
return true;
case ':':
commandProcessor(QSynedit::EditCommand::ecChar,':',nullptr);
//setSelText(key);
if ((caretX() > 2) && (lineText().length() >= 2) &&
(lineText()[caretX() - 3] == ':'))
showCompletion("",false);
showCompletion("",false,CodeCompletionType::Normal);
return true;
case '/':
case '\\':
@ -2975,7 +3008,7 @@ void Editor::exportAsHTML(const QString &htmlFilename)
exporter.SaveToFile(htmlFilename);
}
void Editor::showCompletion(const QString& preWord,bool autoComplete)
void Editor::showCompletion(const QString& preWord,bool autoComplete, CodeCompletionType type)
{
if (pMainWindow->functionTip()->isVisible()) {
pMainWindow->functionTip()->hide();
@ -3089,6 +3122,7 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete)
memberExpression,
mFilename,
caretY(),
type,
keywords);
} else {
QStringList memberExpression;
@ -3096,7 +3130,7 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete)
mCompletionPopup->prepareSearch(preWord,
QStringList(),
"",
memberExpression, mFilename, caretY(),keywords);
memberExpression, mFilename, caretY(),type,keywords);
}
// Filter the whole statement list
@ -4390,6 +4424,59 @@ QString Editor::getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoo
return result;
}
QString Editor::getPreviousWordAtPositionForCompleteFunctionDefinition(const QSynedit::BufferCoord &p)
{
QString result;
if ((p.line<1) || (p.line>document()->count())) {
return "";
}
QString s = document()->getString(p.line - 1);
int wordBegin;
int wordEnd = p.ch-1;
if (wordEnd >= s.length())
wordEnd = s.length()-1;
while (wordEnd > 0 && (isIdentChar(s[wordEnd]) || s[wordEnd] == ':')) {
wordEnd--;
}
int bracketLevel=0;
while (wordEnd > 0) {
if (s[wordEnd] == '>'
|| s[wordEnd] == ']') {
bracketLevel++;
} else if (s[wordEnd] == '<'
|| s[wordEnd] == '[') {
bracketLevel--;
} else if (bracketLevel==0) {
if (s[wordEnd]=='*' || s[wordEnd]=='&' || s[wordEnd]==' ' || s[wordEnd]=='\t') {
//do nothing
} else if (isIdentChar(s[wordEnd]))
break;
else
return ""; //error happened
}
wordEnd--;
}
if (wordEnd<0)
return "";
// if (!isIdentChar(s[wordEnd]))
// return "";
wordBegin = wordEnd;
while ((wordBegin >= 0) && isIdentChar(s[wordBegin]) ) {
wordBegin--;
}
wordBegin++;
if (s[wordBegin]>='0' && s[wordBegin]<='9') // not valid word
return "";
result = s.mid(wordBegin, wordEnd - wordBegin+1);
return result;
}
void Editor::reformat(bool doReparse)
{
if (readOnly())

View File

@ -195,6 +195,7 @@ public:
void modifyBreakpointProperty(int line);
void setActiveBreakpointFocus(int Line, bool setFocus=true);
QString getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoord& p);
QString getPreviousWordAtPositionForCompleteFunctionDefinition(const QSynedit::BufferCoord& p);
void reformat(bool doReparse=true);
void checkSyntaxInBack();
void gotoDeclaration(const QSynedit::BufferCoord& pos);
@ -264,7 +265,7 @@ private:
void undoSymbolCompletion(int pos);
QuoteStatus getQuoteStatus();
void showCompletion(const QString& preWord, bool autoComplete);
void showCompletion(const QString& preWord, bool autoComplete, CodeCompletionType type);
void showHeaderCompletion(bool autoComplete, bool forceShow=false);
bool testInFunc(int x,int y);

View File

@ -987,16 +987,16 @@ bool Project::saveAsTemplate(const QString &templateFolder,
}
ini->SetLongValue("Project", "Type", static_cast<int>(mOptions.type));
if (!mOptions.objFiles.isEmpty())
ini->SetValue("Project", "ObjFiles", mOptions.objFiles.join(";").toUtf8());
if (!mOptions.includeDirs.isEmpty())
ini->SetValue("Project", "Includes", mOptions.includeDirs.join(";").toUtf8());
ini->SetValue("Project", "Includes", extractRelativePaths(directory(), mOptions.includeDirs).join(";").toUtf8());
if (!mOptions.resourceIncludes.isEmpty())
ini->SetValue("Project", "ResourceIncludes", mOptions.resourceIncludes.join(";").toUtf8());
ini->SetValue("Project", "ResourceIncludes", extractRelativePaths(directory(), mOptions.resourceIncludes).join(";").toUtf8());
if (!mOptions.makeIncludes.isEmpty())
ini->SetValue("Project", "MakeIncludes", extractRelativePaths(directory(), mOptions.makeIncludes).join(";").toUtf8());
if (!mOptions.binDirs.isEmpty())
ini->SetValue("Project", "Bins", mOptions.binDirs.join(";").toUtf8());
ini->SetValue("Project", "Bins", extractRelativePaths(directory(), mOptions.binDirs).join(";").toUtf8());
if (!mOptions.libDirs.isEmpty())
ini->SetValue("Project", "Libs", mOptions.libDirs.join(";").toUtf8());
ini->SetValue("Project", "Libs", extractRelativePaths(directory(), mOptions.libDirs).join(";").toUtf8());
if (!mOptions.compilerCmd.isEmpty())
ini->SetValue("Project", "Compiler", mOptions.compilerCmd.toUtf8());
if (!mOptions.cppCompilerCmd.isEmpty())
@ -1078,13 +1078,12 @@ void Project::saveOptions()
ini.SetValue("Project","Name", toByteArray(mName));
ini.SetLongValue("Project","Type", static_cast<int>(mOptions.type));
ini.SetLongValue("Project","Ver", 3); // Is 3 as of Red Panda C++.0
ini.SetValue("Project","ObjFiles", toByteArray(mOptions.objFiles.join(";")));
ini.SetValue("Project","Includes", toByteArray(mOptions.includeDirs.join(";")));
ini.SetValue("Project","Libs", toByteArray(mOptions.libDirs.join(";")));
ini.SetValue("Project","Bins", toByteArray(mOptions.binDirs.join(";")));
ini.SetValue("Project","Includes", toByteArray(extractRelativePaths(directory(),mOptions.includeDirs).join(";")));
ini.SetValue("Project","Libs", toByteArray(extractRelativePaths(directory(),mOptions.libDirs).join(";")));
ini.SetValue("Project","Bins", toByteArray(extractRelativePaths(directory(),mOptions.binDirs).join(";")));
ini.SetValue("Project","PrivateResource", toByteArray(mOptions.privateResource));
ini.SetValue("Project","ResourceIncludes", toByteArray(mOptions.resourceIncludes.join(";")));
ini.SetValue("Project","MakeIncludes", toByteArray(mOptions.makeIncludes.join(";")));
ini.SetValue("Project","ResourceIncludes", toByteArray(extractRelativePaths(directory(),mOptions.resourceIncludes).join(";")));
ini.SetValue("Project","MakeIncludes", toByteArray(extractRelativePaths(directory(),mOptions.makeIncludes).join(";")));
ini.SetValue("Project","Compiler", toByteArray(mOptions.compilerCmd));
ini.SetValue("Project","CppCompiler", toByteArray(mOptions.cppCompilerCmd));
ini.SetValue("Project","Linker", toByteArray(mOptions.linkerCmd));
@ -1096,11 +1095,11 @@ void Project::saveOptions()
ini.SetLongValue("Project","LogOutputEnabled", mOptions.logOutputEnabled);
ini.SetLongValue("Project","OverrideOutput", mOptions.overrideOutput);
ini.SetValue("Project","OverrideOutputName", toByteArray(mOptions.overridenOutput));
ini.SetValue("Project","HostApplication", toByteArray(mOptions.hostApplication));
ini.SetValue("Project","HostApplication", toByteArray(extractRelativePath(directory(), mOptions.hostApplication)));
ini.SetLongValue("Project","UseCustomMakefile", mOptions.useCustomMakefile);
ini.SetValue("Project","CustomMakefile", toByteArray(mOptions.customMakefile));
ini.SetValue("Project","CustomMakefile", toByteArray(extractRelativePath(directory(),mOptions.customMakefile)));
ini.SetLongValue("Project","UsePrecompiledHeader", mOptions.usePrecompiledHeader);
ini.SetValue("Project","PrecompiledHeader", toByteArray(mOptions.precompiledHeader));
ini.SetValue("Project","PrecompiledHeader", toByteArray(extractRelativePath(directory(), mOptions.precompiledHeader)));
ini.SetValue("Project","CommandLine", toByteArray(mOptions.cmdLineArgs));
ini.SetValue("Project","Folders", toByteArray(mFolders.join(";")));
ini.SetLongValue("Project","IncludeVersionInfo", mOptions.includeVersionInfo);
@ -1893,49 +1892,42 @@ void Project::loadOptions(SimpleIni& ini)
mOptions.compilerCmd = fromByteArray(ini.GetValue("Project", "Compiler", ""));
mOptions.cppCompilerCmd = fromByteArray(ini.GetValue("Project", "CppCompiler", ""));
mOptions.linkerCmd = fromByteArray(ini.GetValue("Project", "Linker", ""));
mOptions.objFiles = fromByteArray(ini.GetValue("Project", "ObjFiles", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.binDirs = fromByteArray(ini.GetValue("Project", "Bins", "")).split(";",
mOptions.binDirs = absolutePaths(directory(), fromByteArray(ini.GetValue("Project", "Bins", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.libDirs = fromByteArray(ini.GetValue("Project", "Libs", "")).split(";",
));
mOptions.libDirs = absolutePaths(directory(), fromByteArray(ini.GetValue("Project", "Libs", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.includeDirs = fromByteArray(ini.GetValue("Project", "Includes", "")).split(";",
));
mOptions.includeDirs = absolutePaths(directory(), fromByteArray(ini.GetValue("Project", "Includes", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
));
mOptions.privateResource = fromByteArray(ini.GetValue("Project", "PrivateResource", ""));
mOptions.resourceIncludes = fromByteArray(ini.GetValue("Project", "ResourceIncludes", "")).split(";",
mOptions.resourceIncludes = absolutePaths(directory(), fromByteArray(ini.GetValue("Project", "ResourceIncludes", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.makeIncludes = fromByteArray(ini.GetValue("Project", "MakeIncludes", "")).split(";",
));
mOptions.makeIncludes = absolutePaths(directory(), fromByteArray(ini.GetValue("Project", "MakeIncludes", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
));
mOptions.isCpp = ini.GetBoolValue("Project", "IsCpp", false);
mOptions.exeOutput = fromByteArray(ini.GetValue("Project", "ExeOutput", ""));
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
@ -1943,11 +1935,11 @@ void Project::loadOptions(SimpleIni& ini)
mOptions.logOutputEnabled = ini.GetBoolValue("Project", "LogOutputEnabled", false);
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
mOptions.hostApplication = fromByteArray(ini.GetValue("Project", "HostApplication", ""));
mOptions.hostApplication = absolutePath(directory(), fromByteArray(ini.GetValue("Project", "HostApplication", "")));
mOptions.useCustomMakefile = ini.GetBoolValue("Project", "UseCustomMakefile", false);
mOptions.customMakefile = fromByteArray(ini.GetValue("Project", "CustomMakefile", ""));
mOptions.customMakefile = absolutePath(directory(),fromByteArray(ini.GetValue("Project", "CustomMakefile", "")));
mOptions.usePrecompiledHeader = ini.GetBoolValue("Project", "UsePrecompiledHeader", false);
mOptions.precompiledHeader = fromByteArray(ini.GetValue("Project", "PrecompiledHeader", ""));
mOptions.precompiledHeader = absolutePath(directory(),fromByteArray(ini.GetValue("Project", "PrecompiledHeader", "")));
mOptions.cmdLineArgs = fromByteArray(ini.GetValue("Project", "CommandLine", ""));
mFolders = fromByteArray(ini.GetValue("Project", "Folders", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
@ -2091,13 +2083,6 @@ void Project::loadOptions(SimpleIni& ini)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.objFiles = fromByteArray(ini.GetValue("Project", "ObjFiles", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.includeDirs = fromByteArray(ini.GetValue("Project", "IncludeDirs", "")).split(";",
@ -2113,7 +2098,7 @@ void Project::loadOptions(SimpleIni& ini)
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
mOptions.hostApplication = fromByteArray(ini.GetValue("Project", "HostApplication", ""));
mOptions.hostApplication = absolutePath(directory(), fromByteArray(ini.GetValue("Project", "HostApplication", "")));
}
}

View File

@ -63,7 +63,6 @@ struct ProjectOptions{
explicit ProjectOptions();
ProjectType type;
int version;
QStringList objFiles;
QString compilerCmd;
QString cppCompilerCmd;
QString linkerCmd;

View File

@ -104,13 +104,6 @@ void ProjectTemplate::readTemplateFile(const QString &fileName)
mOptions.icon = mIni->GetValue("Project", "Icon", "");
mOptions.type = static_cast<ProjectType>(mIni->GetLongValue("Project", "Type", 0)); // default = gui
mOptions.objFiles = fromByteArray(mIni->GetValue("Project", "ObjFiles", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts
#else
QString::SkipEmptyParts
#endif
);
mOptions.includeDirs = fromByteArray(mIni->GetValue("Project", "Includes", "")).split(";",
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
Qt::SkipEmptyParts

View File

@ -80,6 +80,7 @@ void CodeCompletionPopup::prepareSearch(
const QStringList& memberExpression,
const QString &filename,
int line,
CodeCompletionType type,
const QSet<QString>& customKeywords)
{
QMutexLocker locker(&mMutex);
@ -91,11 +92,14 @@ void CodeCompletionPopup::prepareSearch(
mMemberPhrase = memberExpression.join("");
mMemberOperator = memberOperator;
if (preWord.isEmpty()) {
if (type == CodeCompletionType::TypeKeywordComplex) {
getCompletionListForTypeKeywordComplex(preWord);
} else if (type == CodeCompletionType::FunctionWithoutDefinition) {
mIncludedFiles = mParser->getFileIncludes(filename);
getCompletionForFunctionWithoutDefinition(preWord, ownerExpression,memberOperator,memberExpression, filename,line);
} else if (preWord.isEmpty()) {
mIncludedFiles = mParser->getFileIncludes(filename);
getCompletionFor(ownerExpression,memberOperator,memberExpression, filename,line, customKeywords);
} else {
getCompletionListForPreWord(preWord);
}
setCursor(oldCursor);
@ -198,6 +202,40 @@ void CodeCompletionPopup::addChildren(PStatement scopeStatement, const QString &
}
}
void CodeCompletionPopup::addFunctionWithoutDefinitionChildren(PStatement scopeStatement, const QString &fileName, int line)
{
if (scopeStatement && !isIncluded(scopeStatement->fileName)
&& !isIncluded(scopeStatement->definitionFileName))
return;
const StatementMap& children = mParser->statementList().childrenStatements(scopeStatement);
if (children.isEmpty())
return;
for (const PStatement& childStatement: children) {
if (childStatement->inSystemHeader)
continue;
if (childStatement->fileName.isEmpty()) {
// hard defines, do nothing
continue;
}
switch(childStatement->kind) {
case StatementKind::skConstructor:
case StatementKind::skFunction:
case StatementKind::skDestructor:
if (!childStatement->hasDefinition)
addStatement(childStatement,fileName,line);
break;
case StatementKind::skClass:
case StatementKind::skNamespace:
if (isIncluded(childStatement->fileName))
addStatement(childStatement,fileName,line);
break;
default:
break;
}
}
}
void CodeCompletionPopup::addStatement(PStatement statement, const QString &fileName, int line)
{
if (mAddedStatements.contains(statement->command))
@ -766,7 +804,84 @@ void CodeCompletionPopup::getCompletionFor(
}
}
void CodeCompletionPopup::getCompletionListForPreWord(const QString &preWord)
void CodeCompletionPopup::getCompletionForFunctionWithoutDefinition(const QString& preWord, const QStringList &ownerExpression, const QString &memberOperator, const QStringList &memberExpression, const QString &fileName, int line)
{
if(!mParser) {
return;
}
if (!mParser->enabled())
return;
if (memberOperator.isEmpty() && ownerExpression.isEmpty() && memberExpression.isEmpty())
return;
if (!mParser->freeze())
return;
{
auto action = finally([this]{
mParser->unFreeze();
});
if (memberOperator.isEmpty()) {
getCompletionListForTypeKeywordComplex(preWord);
PStatement scopeStatement = mCurrentScope;
//add members of current scope that not added before
while (scopeStatement && scopeStatement->kind!=StatementKind::skNamespace) {
scopeStatement = scopeStatement->parentScope.lock();
}
if (scopeStatement) {
//namespace;
PStatementList namespaceStatementsList =
mParser->findNamespace(scopeStatement->fullName);
if (namespaceStatementsList) {
foreach (const PStatement& namespaceStatement, *namespaceStatementsList) {
addFunctionWithoutDefinitionChildren(namespaceStatement, fileName, line);
}
}
} else {
//global
addFunctionWithoutDefinitionChildren(scopeStatement, fileName, line);
}
} else {
if (memberOperator != "::")
return;
//the identifier to be completed is a member of variable/class
if (ownerExpression.isEmpty()) {
// start with '::', we only find in global
// add all global members and not added before
addFunctionWithoutDefinitionChildren(nullptr, fileName, line);
return;
}
if (memberExpression.length()==2 && memberExpression.front()!="~")
return;
if (memberExpression.length()>2)
return;
PStatement scope = mCurrentScope;//the scope the expression in
PStatement parentTypeStatement;
PEvalStatement ownerStatement = mParser->evalExpression(fileName,
ownerExpression,
scope);
if(!ownerStatement || !ownerStatement->effectiveTypeStatement) {
return;
}
if (ownerStatement->kind==EvalStatementKind::Namespace) {
//there might be many statements corresponding to one namespace;
PStatementList namespaceStatementsList =
mParser->findNamespace(ownerStatement->baseType);
if (namespaceStatementsList) {
foreach (const PStatement& namespaceStatement, *namespaceStatementsList) {
addFunctionWithoutDefinitionChildren(namespaceStatement, fileName, line);
}
}
return;
} else if (ownerStatement->effectiveTypeStatement->kind == StatementKind::skClass) {
addFunctionWithoutDefinitionChildren(ownerStatement->effectiveTypeStatement, fileName, line);
}
}
}
}
void CodeCompletionPopup::getCompletionListForTypeKeywordComplex(const QString &preWord)
{
mFullCompletionStatementList.clear();
if (preWord == "long") {

View File

@ -39,7 +39,7 @@ private:
enum class CodeCompletionType {
Normal,
ComplexType,
TypeKeywordComplex,
FunctionWithoutDefinition
};
@ -86,6 +86,7 @@ public:
const QStringList& memberExpression,
const QString& filename,
int line,
CodeCompletionType completionType,
const QSet<QString>& customKeywords);
bool search(const QString& memberPhrase, bool autoHideOnSingleResult);
@ -127,6 +128,8 @@ public:
private:
void addChildren(PStatement scopeStatement, const QString& fileName,
int line);
void addFunctionWithoutDefinitionChildren(PStatement scopeStatement, const QString& fileName,
int line);
void addStatement(PStatement statement, const QString& fileName, int line);
void filterList(const QString& member);
void getCompletionFor(
@ -136,7 +139,16 @@ private:
const QString& fileName,
int line,
const QSet<QString>& customKeywords);
void getCompletionListForPreWord(const QString& preWord);
void getCompletionForFunctionWithoutDefinition(
const QString& preWord,
const QStringList& ownerExpression,
const QString& memberOperator,
const QStringList& memberExpression,
const QString& fileName,
int line);
void getCompletionListForTypeKeywordComplex(const QString& preWord);
void addKeyword(const QString& keyword);
bool isIncluded(const QString& fileName);
private: