- enhancement: show completion tips for when define a function that already has a declaration.
- clean up code
This commit is contained in:
parent
9072e752a0
commit
eceba8b8f2
1
NEWS.md
1
NEWS.md
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
showCompletion("",false,CodeCompletionType::FunctionWithoutDefinition);
|
||||
handled=true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
||||
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())
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(";",
|
||||
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.binDirs = fromByteArray(ini.GetValue("Project", "Bins", "")).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.libDirs = fromByteArray(ini.GetValue("Project", "Libs", "")).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.includeDirs = 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", "")));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,6 @@ struct ProjectOptions{
|
|||
explicit ProjectOptions();
|
||||
ProjectType type;
|
||||
int version;
|
||||
QStringList objFiles;
|
||||
QString compilerCmd;
|
||||
QString cppCompilerCmd;
|
||||
QString linkerCmd;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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") {
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue