- 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: var assignment not correctly handled in code parser;
|
||||||
- fix: function args not correctly handled in code parser;
|
- fix: function args not correctly handled in code parser;
|
||||||
- fix: crash when alt+mouse drag selection
|
- 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
|
Red Panda C++ Version 2.3
|
||||||
|
|
||||||
|
|
|
@ -731,24 +731,28 @@ void Editor::keyPressEvent(QKeyEvent *event)
|
||||||
QString lastWord = getPreviousWordAtPositionForSuggestion(caretXY());
|
QString lastWord = getPreviousWordAtPositionForSuggestion(caretXY());
|
||||||
if (mParser && !lastWord.isEmpty()) {
|
if (mParser && !lastWord.isEmpty()) {
|
||||||
if (CppTypeKeywords.contains(lastWord)) {
|
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" ||
|
if (lastWord == "long" ||
|
||||||
lastWord == "short" ||
|
lastWord == "short" ||
|
||||||
lastWord == "signed" ||
|
lastWord == "signed" ||
|
||||||
lastWord == "unsigned"
|
lastWord == "unsigned"
|
||||||
) {
|
) {
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
||||||
showCompletion(lastWord,false);
|
showCompletion(lastWord,false, CodeCompletionType::TypeKeywordComplex);
|
||||||
handled=true;
|
handled=true;
|
||||||
return;
|
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
|
//last word is a type keyword, this is a var or param define, and dont show suggestion
|
||||||
return;
|
return;
|
||||||
|
@ -762,12 +766,41 @@ void Editor::keyPressEvent(QKeyEvent *event)
|
||||||
|| kind == StatementKind::skEnumClassType
|
|| kind == StatementKind::skEnumClassType
|
||||||
|| kind == StatementKind::skEnumType
|
|| kind == StatementKind::skEnumType
|
||||||
|| kind == StatementKind::skTypedef) {
|
|| 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
|
//last word is a typedef/class/struct, this is a var or param define, and dont show suggestion
|
||||||
return;
|
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);
|
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
handled=true;
|
handled=true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -779,7 +812,7 @@ void Editor::keyPressEvent(QKeyEvent *event)
|
||||||
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
|
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
|
||||||
mLastIdCharPressed++;
|
mLastIdCharPressed++;
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
handled=true;
|
handled=true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -791,7 +824,7 @@ void Editor::keyPressEvent(QKeyEvent *event)
|
||||||
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
|
&& pSettings->codeCompletion().showCompletionWhileInput() ) {
|
||||||
mLastIdCharPressed++;
|
mLastIdCharPressed++;
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
commandProcessor(QSynedit::EditCommand::ecChar,ch,nullptr);
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
handled=true;
|
handled=true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1302,7 @@ void Editor::inputMethodEvent(QInputMethodEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2564,20 +2597,20 @@ bool Editor::handleCodeCompletion(QChar key)
|
||||||
switch(key.unicode()) {
|
switch(key.unicode()) {
|
||||||
case '.':
|
case '.':
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar, key);
|
commandProcessor(QSynedit::EditCommand::ecChar, key);
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
return true;
|
return true;
|
||||||
case '>':
|
case '>':
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar, key);
|
commandProcessor(QSynedit::EditCommand::ecChar, key);
|
||||||
if ((caretX() > 2) && (lineText().length() >= 2) &&
|
if ((caretX() > 2) && (lineText().length() >= 2) &&
|
||||||
(lineText()[caretX() - 3] == '-'))
|
(lineText()[caretX() - 3] == '-'))
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
return true;
|
return true;
|
||||||
case ':':
|
case ':':
|
||||||
commandProcessor(QSynedit::EditCommand::ecChar,':',nullptr);
|
commandProcessor(QSynedit::EditCommand::ecChar,':',nullptr);
|
||||||
//setSelText(key);
|
//setSelText(key);
|
||||||
if ((caretX() > 2) && (lineText().length() >= 2) &&
|
if ((caretX() > 2) && (lineText().length() >= 2) &&
|
||||||
(lineText()[caretX() - 3] == ':'))
|
(lineText()[caretX() - 3] == ':'))
|
||||||
showCompletion("",false);
|
showCompletion("",false,CodeCompletionType::Normal);
|
||||||
return true;
|
return true;
|
||||||
case '/':
|
case '/':
|
||||||
case '\\':
|
case '\\':
|
||||||
|
@ -2975,7 +3008,7 @@ void Editor::exportAsHTML(const QString &htmlFilename)
|
||||||
exporter.SaveToFile(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()) {
|
if (pMainWindow->functionTip()->isVisible()) {
|
||||||
pMainWindow->functionTip()->hide();
|
pMainWindow->functionTip()->hide();
|
||||||
|
@ -3089,6 +3122,7 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete)
|
||||||
memberExpression,
|
memberExpression,
|
||||||
mFilename,
|
mFilename,
|
||||||
caretY(),
|
caretY(),
|
||||||
|
type,
|
||||||
keywords);
|
keywords);
|
||||||
} else {
|
} else {
|
||||||
QStringList memberExpression;
|
QStringList memberExpression;
|
||||||
|
@ -3096,7 +3130,7 @@ void Editor::showCompletion(const QString& preWord,bool autoComplete)
|
||||||
mCompletionPopup->prepareSearch(preWord,
|
mCompletionPopup->prepareSearch(preWord,
|
||||||
QStringList(),
|
QStringList(),
|
||||||
"",
|
"",
|
||||||
memberExpression, mFilename, caretY(),keywords);
|
memberExpression, mFilename, caretY(),type,keywords);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter the whole statement list
|
// Filter the whole statement list
|
||||||
|
@ -4390,6 +4424,59 @@ QString Editor::getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoo
|
||||||
return result;
|
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)
|
void Editor::reformat(bool doReparse)
|
||||||
{
|
{
|
||||||
if (readOnly())
|
if (readOnly())
|
||||||
|
|
|
@ -195,6 +195,7 @@ public:
|
||||||
void modifyBreakpointProperty(int line);
|
void modifyBreakpointProperty(int line);
|
||||||
void setActiveBreakpointFocus(int Line, bool setFocus=true);
|
void setActiveBreakpointFocus(int Line, bool setFocus=true);
|
||||||
QString getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoord& p);
|
QString getPreviousWordAtPositionForSuggestion(const QSynedit::BufferCoord& p);
|
||||||
|
QString getPreviousWordAtPositionForCompleteFunctionDefinition(const QSynedit::BufferCoord& p);
|
||||||
void reformat(bool doReparse=true);
|
void reformat(bool doReparse=true);
|
||||||
void checkSyntaxInBack();
|
void checkSyntaxInBack();
|
||||||
void gotoDeclaration(const QSynedit::BufferCoord& pos);
|
void gotoDeclaration(const QSynedit::BufferCoord& pos);
|
||||||
|
@ -264,7 +265,7 @@ private:
|
||||||
void undoSymbolCompletion(int pos);
|
void undoSymbolCompletion(int pos);
|
||||||
QuoteStatus getQuoteStatus();
|
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);
|
void showHeaderCompletion(bool autoComplete, bool forceShow=false);
|
||||||
|
|
||||||
bool testInFunc(int x,int y);
|
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));
|
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())
|
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())
|
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())
|
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())
|
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())
|
if (!mOptions.compilerCmd.isEmpty())
|
||||||
ini->SetValue("Project", "Compiler", mOptions.compilerCmd.toUtf8());
|
ini->SetValue("Project", "Compiler", mOptions.compilerCmd.toUtf8());
|
||||||
if (!mOptions.cppCompilerCmd.isEmpty())
|
if (!mOptions.cppCompilerCmd.isEmpty())
|
||||||
|
@ -1078,13 +1078,12 @@ void Project::saveOptions()
|
||||||
ini.SetValue("Project","Name", toByteArray(mName));
|
ini.SetValue("Project","Name", toByteArray(mName));
|
||||||
ini.SetLongValue("Project","Type", static_cast<int>(mOptions.type));
|
ini.SetLongValue("Project","Type", static_cast<int>(mOptions.type));
|
||||||
ini.SetLongValue("Project","Ver", 3); // Is 3 as of Red Panda C++.0
|
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(extractRelativePaths(directory(),mOptions.includeDirs).join(";")));
|
||||||
ini.SetValue("Project","Includes", toByteArray(mOptions.includeDirs.join(";")));
|
ini.SetValue("Project","Libs", toByteArray(extractRelativePaths(directory(),mOptions.libDirs).join(";")));
|
||||||
ini.SetValue("Project","Libs", toByteArray(mOptions.libDirs.join(";")));
|
ini.SetValue("Project","Bins", toByteArray(extractRelativePaths(directory(),mOptions.binDirs).join(";")));
|
||||||
ini.SetValue("Project","Bins", toByteArray(mOptions.binDirs.join(";")));
|
|
||||||
ini.SetValue("Project","PrivateResource", toByteArray(mOptions.privateResource));
|
ini.SetValue("Project","PrivateResource", toByteArray(mOptions.privateResource));
|
||||||
ini.SetValue("Project","ResourceIncludes", toByteArray(mOptions.resourceIncludes.join(";")));
|
ini.SetValue("Project","ResourceIncludes", toByteArray(extractRelativePaths(directory(),mOptions.resourceIncludes).join(";")));
|
||||||
ini.SetValue("Project","MakeIncludes", toByteArray(mOptions.makeIncludes.join(";")));
|
ini.SetValue("Project","MakeIncludes", toByteArray(extractRelativePaths(directory(),mOptions.makeIncludes).join(";")));
|
||||||
ini.SetValue("Project","Compiler", toByteArray(mOptions.compilerCmd));
|
ini.SetValue("Project","Compiler", toByteArray(mOptions.compilerCmd));
|
||||||
ini.SetValue("Project","CppCompiler", toByteArray(mOptions.cppCompilerCmd));
|
ini.SetValue("Project","CppCompiler", toByteArray(mOptions.cppCompilerCmd));
|
||||||
ini.SetValue("Project","Linker", toByteArray(mOptions.linkerCmd));
|
ini.SetValue("Project","Linker", toByteArray(mOptions.linkerCmd));
|
||||||
|
@ -1096,11 +1095,11 @@ void Project::saveOptions()
|
||||||
ini.SetLongValue("Project","LogOutputEnabled", mOptions.logOutputEnabled);
|
ini.SetLongValue("Project","LogOutputEnabled", mOptions.logOutputEnabled);
|
||||||
ini.SetLongValue("Project","OverrideOutput", mOptions.overrideOutput);
|
ini.SetLongValue("Project","OverrideOutput", mOptions.overrideOutput);
|
||||||
ini.SetValue("Project","OverrideOutputName", toByteArray(mOptions.overridenOutput));
|
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.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.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","CommandLine", toByteArray(mOptions.cmdLineArgs));
|
||||||
ini.SetValue("Project","Folders", toByteArray(mFolders.join(";")));
|
ini.SetValue("Project","Folders", toByteArray(mFolders.join(";")));
|
||||||
ini.SetLongValue("Project","IncludeVersionInfo", mOptions.includeVersionInfo);
|
ini.SetLongValue("Project","IncludeVersionInfo", mOptions.includeVersionInfo);
|
||||||
|
@ -1893,49 +1892,42 @@ void Project::loadOptions(SimpleIni& ini)
|
||||||
mOptions.compilerCmd = fromByteArray(ini.GetValue("Project", "Compiler", ""));
|
mOptions.compilerCmd = fromByteArray(ini.GetValue("Project", "Compiler", ""));
|
||||||
mOptions.cppCompilerCmd = fromByteArray(ini.GetValue("Project", "CppCompiler", ""));
|
mOptions.cppCompilerCmd = fromByteArray(ini.GetValue("Project", "CppCompiler", ""));
|
||||||
mOptions.linkerCmd = fromByteArray(ini.GetValue("Project", "Linker", ""));
|
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(";",
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
QString::SkipEmptyParts
|
||||||
#endif
|
#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)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
QString::SkipEmptyParts
|
||||||
#endif
|
#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)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
QString::SkipEmptyParts
|
||||||
#endif
|
#endif
|
||||||
);
|
));
|
||||||
mOptions.privateResource = fromByteArray(ini.GetValue("Project", "PrivateResource", ""));
|
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)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
QString::SkipEmptyParts
|
||||||
#endif
|
#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)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
QString::SkipEmptyParts
|
||||||
#endif
|
#endif
|
||||||
);
|
));
|
||||||
mOptions.isCpp = ini.GetBoolValue("Project", "IsCpp", false);
|
mOptions.isCpp = ini.GetBoolValue("Project", "IsCpp", false);
|
||||||
mOptions.exeOutput = fromByteArray(ini.GetValue("Project", "ExeOutput", ""));
|
mOptions.exeOutput = fromByteArray(ini.GetValue("Project", "ExeOutput", ""));
|
||||||
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
|
mOptions.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
|
||||||
|
@ -1943,11 +1935,11 @@ void Project::loadOptions(SimpleIni& ini)
|
||||||
mOptions.logOutputEnabled = ini.GetBoolValue("Project", "LogOutputEnabled", false);
|
mOptions.logOutputEnabled = ini.GetBoolValue("Project", "LogOutputEnabled", false);
|
||||||
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
||||||
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
|
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.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.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", ""));
|
mOptions.cmdLineArgs = fromByteArray(ini.GetValue("Project", "CommandLine", ""));
|
||||||
mFolders = fromByteArray(ini.GetValue("Project", "Folders", "")).split(";",
|
mFolders = fromByteArray(ini.GetValue("Project", "Folders", "")).split(";",
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
|
@ -2091,13 +2083,6 @@ void Project::loadOptions(SimpleIni& ini)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
#else
|
#else
|
||||||
QString::SkipEmptyParts
|
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
|
#endif
|
||||||
);
|
);
|
||||||
mOptions.includeDirs = fromByteArray(ini.GetValue("Project", "IncludeDirs", "")).split(";",
|
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.objectOutput = fromByteArray(ini.GetValue("Project", "ObjectOutput", ""));
|
||||||
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
mOptions.overrideOutput = ini.GetBoolValue("Project", "OverrideOutput", false);
|
||||||
mOptions.overridenOutput = fromByteArray(ini.GetValue("Project", "OverrideOutputName", ""));
|
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();
|
explicit ProjectOptions();
|
||||||
ProjectType type;
|
ProjectType type;
|
||||||
int version;
|
int version;
|
||||||
QStringList objFiles;
|
|
||||||
QString compilerCmd;
|
QString compilerCmd;
|
||||||
QString cppCompilerCmd;
|
QString cppCompilerCmd;
|
||||||
QString linkerCmd;
|
QString linkerCmd;
|
||||||
|
|
|
@ -104,13 +104,6 @@ void ProjectTemplate::readTemplateFile(const QString &fileName)
|
||||||
|
|
||||||
mOptions.icon = mIni->GetValue("Project", "Icon", "");
|
mOptions.icon = mIni->GetValue("Project", "Icon", "");
|
||||||
mOptions.type = static_cast<ProjectType>(mIni->GetLongValue("Project", "Type", 0)); // default = gui
|
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(";",
|
mOptions.includeDirs = fromByteArray(mIni->GetValue("Project", "Includes", "")).split(";",
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5,15,0)
|
||||||
Qt::SkipEmptyParts
|
Qt::SkipEmptyParts
|
||||||
|
|
|
@ -80,6 +80,7 @@ void CodeCompletionPopup::prepareSearch(
|
||||||
const QStringList& memberExpression,
|
const QStringList& memberExpression,
|
||||||
const QString &filename,
|
const QString &filename,
|
||||||
int line,
|
int line,
|
||||||
|
CodeCompletionType type,
|
||||||
const QSet<QString>& customKeywords)
|
const QSet<QString>& customKeywords)
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&mMutex);
|
QMutexLocker locker(&mMutex);
|
||||||
|
@ -91,11 +92,14 @@ void CodeCompletionPopup::prepareSearch(
|
||||||
|
|
||||||
mMemberPhrase = memberExpression.join("");
|
mMemberPhrase = memberExpression.join("");
|
||||||
mMemberOperator = memberOperator;
|
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);
|
mIncludedFiles = mParser->getFileIncludes(filename);
|
||||||
getCompletionFor(ownerExpression,memberOperator,memberExpression, filename,line, customKeywords);
|
getCompletionFor(ownerExpression,memberOperator,memberExpression, filename,line, customKeywords);
|
||||||
} else {
|
|
||||||
getCompletionListForPreWord(preWord);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setCursor(oldCursor);
|
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)
|
void CodeCompletionPopup::addStatement(PStatement statement, const QString &fileName, int line)
|
||||||
{
|
{
|
||||||
if (mAddedStatements.contains(statement->command))
|
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();
|
mFullCompletionStatementList.clear();
|
||||||
if (preWord == "long") {
|
if (preWord == "long") {
|
||||||
|
|
|
@ -39,7 +39,7 @@ private:
|
||||||
|
|
||||||
enum class CodeCompletionType {
|
enum class CodeCompletionType {
|
||||||
Normal,
|
Normal,
|
||||||
ComplexType,
|
TypeKeywordComplex,
|
||||||
FunctionWithoutDefinition
|
FunctionWithoutDefinition
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ public:
|
||||||
const QStringList& memberExpression,
|
const QStringList& memberExpression,
|
||||||
const QString& filename,
|
const QString& filename,
|
||||||
int line,
|
int line,
|
||||||
|
CodeCompletionType completionType,
|
||||||
const QSet<QString>& customKeywords);
|
const QSet<QString>& customKeywords);
|
||||||
bool search(const QString& memberPhrase, bool autoHideOnSingleResult);
|
bool search(const QString& memberPhrase, bool autoHideOnSingleResult);
|
||||||
|
|
||||||
|
@ -127,6 +128,8 @@ public:
|
||||||
private:
|
private:
|
||||||
void addChildren(PStatement scopeStatement, const QString& fileName,
|
void addChildren(PStatement scopeStatement, const QString& fileName,
|
||||||
int line);
|
int line);
|
||||||
|
void addFunctionWithoutDefinitionChildren(PStatement scopeStatement, const QString& fileName,
|
||||||
|
int line);
|
||||||
void addStatement(PStatement statement, const QString& fileName, int line);
|
void addStatement(PStatement statement, const QString& fileName, int line);
|
||||||
void filterList(const QString& member);
|
void filterList(const QString& member);
|
||||||
void getCompletionFor(
|
void getCompletionFor(
|
||||||
|
@ -136,7 +139,16 @@ private:
|
||||||
const QString& fileName,
|
const QString& fileName,
|
||||||
int line,
|
int line,
|
||||||
const QSet<QString>& customKeywords);
|
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);
|
void addKeyword(const QString& keyword);
|
||||||
bool isIncluded(const QString& fileName);
|
bool isIncluded(const QString& fileName);
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue