work save

This commit is contained in:
royqh1979@gmail.com 2021-08-24 15:05:10 +08:00
parent 74f2d689d6
commit ea77b45661
9 changed files with 309 additions and 43 deletions

View File

@ -139,7 +139,6 @@ HEADERS += \
FORMS += \
settingsdialog/debuggeneralwidget.ui \
widgets/codecompletionview.ui \
widgets/cpudialog.ui \
mainwindow.ui \
settingsdialog/compilersetdirectorieswidget.ui \

View File

@ -3525,6 +3525,11 @@ void CppParser::updateSerialId()
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
}
const StatementModel &CppParser::statementList() const
{
return mStatementList;
}
bool CppParser::parseGlobalHeaders() const
{
return mParseGlobalHeaders;

View File

@ -119,6 +119,8 @@ public:
bool parseGlobalHeaders() const;
void setParseGlobalHeaders(bool newParseGlobalHeaders);
const StatementModel &statementList() const;
signals:
void onProgress(const QString& fileName, int total, int current);
void onBusy();

View File

@ -4,6 +4,17 @@
#include <QObject>
#include <QSet>
#include <memory>
struct CodeIns {
QString caption; //Name
QString prefix; //Prefix used in code suggestion
QString code; //Code body
QString desc; //Description
int section; //Section in the menu
};
using PCodeIns = std::shared_ptr<CodeIns>;
// preprocess/ macro define
struct Define {
QString name;
@ -190,4 +201,5 @@ bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePat
bool isHfile(const QString filename);
bool isCfile(const QString filename);
bool isKeyword(const QString& word);
#endif // PARSER_UTILS_H

View File

@ -37,7 +37,7 @@ void StatementModel::deleteStatement(PStatement statement)
mCount -= count;
}
const StatementMap &StatementModel::childrenStatements(PStatement statement)
const StatementMap &StatementModel::childrenStatements(PStatement statement) const
{
if (!statement) {
return mGlobalStatements;
@ -46,7 +46,7 @@ const StatementMap &StatementModel::childrenStatements(PStatement statement)
}
}
const StatementMap &StatementModel::childrenStatements(std::weak_ptr<Statement> statement)
const StatementMap &StatementModel::childrenStatements(std::weak_ptr<Statement> statement) const
{
PStatement s = statement.lock();
return childrenStatements(s);

View File

@ -15,8 +15,8 @@ public:
// function DeleteFirst: Integer;
// function DeleteLast: Integer;
void deleteStatement(PStatement statement);
const StatementMap& childrenStatements(PStatement statement = PStatement());
const StatementMap& childrenStatements(std::weak_ptr<Statement> statement);
const StatementMap& childrenStatements(PStatement statement = PStatement()) const;
const StatementMap& childrenStatements(std::weak_ptr<Statement> statement) const;
void clear();
void dump(const QString& logFile);

View File

@ -1,7 +1,8 @@
#include "codecompletionview.h"
#include "ui_codecompletionview.h"
#include "../utils.h"
#include <QKeyEvent>
#include <QVBoxLayout>
CodeCompletionView::CodeCompletionView(QWidget *parent) :
QWidget(parent)
@ -23,6 +24,257 @@ void CodeCompletionView::setKeypressedCallback(const KeyPressedCallback &newKeyp
mListView->setKeypressedCallback(newKeypressedCallback);
}
void CodeCompletionView::addChildren(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;
if (!scopeStatement) { //Global scope
for (PStatement childStatement: children) {
if (childStatement->fileName.isEmpty()) {
// hard defines
addStatement(childStatement,fileName,-1);
} else if (!( childStatement->kind == StatementKind::skConstructor
|| childStatement->kind == StatementKind::skDestructor
|| childStatement->kind == StatementKind::skBlock)
&& (!mAddedStatements.contains(childStatement->command))
&& (
isIncluded(childStatement->fileName)
|| isIncluded(childStatement->definitionFileName)
)
) {
//we must check if the statement is included by the file
addStatement(childStatement,fileName,line);
}
}
} else {
for (PStatement childStatement: children) {
if (!( childStatement->kind == StatementKind::skConstructor
|| childStatement->kind == StatementKind::skDestructor
|| childStatement->kind == StatementKind::skBlock)
&& (!mAddedStatements.contains(childStatement->command)))
addStatement(childStatement,fileName,line);
}
}
}
void CodeCompletionView::addStatement(PStatement statement, const QString &fileName, int line)
{
if ((line!=-1)
&& (line < statement->line)
&& (fileName == statement->fileName))
return;
mAddedStatements.insert(statement->command);
mFullCompletionStatementList.append(statement);
}
static bool defaultComparator(PStatement statement1,PStatement statement2) {
// Show user template first
if (statement1->kind == StatementKind::skUserCodeIn) {
if (statement2->kind != StatementKind::skUserCodeIn)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skUserCodeIn) {
return false;
// show keywords first
} else if ((statement1->kind == StatementKind::skKeyword)
&& (statement2->kind != StatementKind::skKeyword)) {
return true;
} else if ((statement1->kind != StatementKind::skKeyword)
&& (statement2->kind == StatementKind::skKeyword)) {
return false;
} else
return statement1->command < statement2->command;
}
static bool sortByScopeComparator(PStatement statement1,PStatement statement2){
// Show user template first
if (statement1->kind == StatementKind::skUserCodeIn) {
if (statement2->kind != StatementKind::skUserCodeIn)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skUserCodeIn) {
return false;
// show keywords first
} else if (statement1->kind == StatementKind::skKeyword) {
if (statement2->kind != StatementKind::skKeyword)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skKeyword) {
return false;
// Show stuff from local headers first
} else if (statement1->inSystemHeader && ! statement2->inSystemHeader) {
return true;
} else if (!statement1->inSystemHeader && statement2->inSystemHeader) {
return false;
// Show local statements first
} else if (statement1->scope != StatementScope::ssGlobal
&& statement1->scope == StatementScope::ssGlobal ) {
return true;
} else if (statement1->scope == StatementScope::ssGlobal
&& statement1->scope != StatementScope::ssGlobal ) {
return false;
// otherwise, sort by name
} else
return statement1->command < statement2->command;
}
static bool sortWithUsageComparator(PStatement statement1,PStatement statement2) {
// Show user template first
if (statement1->kind == StatementKind::skUserCodeIn) {
if (statement2->kind != StatementKind::skUserCodeIn)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skUserCodeIn) {
return false;
//show most freq first
} else if (statement1->freqTop > statement2->freqTop) {
return true;
} else if (statement1->freqTop < statement2->freqTop) {
return false;
// show keywords first
} else if ((statement1->kind == StatementKind::skKeyword)
&& (statement2->kind != StatementKind::skKeyword)) {
return true;
} else if ((statement1->kind != StatementKind::skKeyword)
&& (statement2->kind == StatementKind::skKeyword)) {
return false;
} else
return statement1->command < statement2->command;
}
static bool sortByScopeWithUsageComparator(PStatement statement1,PStatement statement2){
// Show user template first
if (statement1->kind == StatementKind::skUserCodeIn) {
if (statement2->kind != StatementKind::skUserCodeIn)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skUserCodeIn) {
return false;
//show most freq first
} else if (statement1->freqTop > statement2->freqTop) {
return true;
} else if (statement1->freqTop < statement2->freqTop) {
return false;
// show keywords first
} else if (statement1->kind == StatementKind::skKeyword) {
if (statement2->kind != StatementKind::skKeyword)
return true;
else
return statement1->command < statement2->command;
} else if (statement2->kind == StatementKind::skKeyword) {
return false;
// Show stuff from local headers first
} else if (statement1->inSystemHeader && ! statement2->inSystemHeader) {
return true;
} else if (!statement1->inSystemHeader && statement2->inSystemHeader) {
return false;
// Show local statements first
} else if (statement1->scope != StatementScope::ssGlobal
&& statement1->scope == StatementScope::ssGlobal ) {
return true;
} else if (statement1->scope == StatementScope::ssGlobal
&& statement1->scope != StatementScope::ssGlobal ) {
return false;
// otherwise, sort by name
} else
return statement1->command < statement2->command;
}
void CodeCompletionView::filterList(const QString &member)
{
QMutexLocker locker(&mMutex);
mCompletionStatementList.clear();
if (!mParser)
return;
if (!mParser->enabled())
return;
//we don't need to freeze here since we use smart pointers
// and data have been retrieved from the parser
// if (!mParser->freeze())
// return;
// {
// auto action = finally([this]{
// mParser->unFreeze();
// });
// if (mParserSerialId!=mParser->serialId()) {
// return;
// }
QList<PStatement> tmpList;
if (!member.isEmpty()) { // filter
tmpList.reserve(mFullCompletionStatementList.size());
for (PStatement statement:mFullCompletionStatementList) {
Qt::CaseSensitivity cs = (mIgnoreCase?
Qt::CaseInsensitive:
Qt::CaseSensitive);
if (statement->command.startsWith(member, cs))
tmpList.append(statement);
}
} else
tmpList = mCompletionStatementList;
if (mRecordUsage) {
int topCount = 0;
int secondCount = 0;
int thirdCount = 0;
int usageCount;
for (PStatement statement:tmpList) {
if (statement->usageCount == 0) {
usageCount = mSymbolUsage.value(statement->fullName,0);
if (usageCount == 0)
continue;
statement->usageCount = usageCount;
} else
usageCount = statement->usageCount;
if (usageCount>topCount) {
thirdCount = secondCount;
secondCount = topCount;
topCount = usageCount;
} else if (usageCount == topCount) {
continue;
} else if (usageCount > secondCount) {
thirdCount = secondCount;
secondCount = usageCount;
} else if (usageCount == secondCount) {
continue;
} else if (usageCount>thirdCount) {
thirdCount = usageCount;
}
}
for (PStatement statement:tmpList) {
if (statement->usageCount == 0) {
statement->freqTop = 0;
} else if (statement->usageCount == topCount) {
statement->freqTop = 30;
} else if (statement->usageCount == secondCount) {
statement->freqTop = 20;
} else if (statement->usageCount == thirdCount) {
statement->freqTop = 10;
}
}
if (mSortByScope) {
std::sort(tmpList.begin(),tmpList.end(),sortByScopeWithUsageComparator);
} else {
std::sort(tmpList.begin(),tmpList.end(),sortWithUsageComparator);
}
} else if (mSortByScope) {
std::sort(tmpList.begin(),tmpList.end(),sortByScopeComparator);
} else {
std::sort(tmpList.begin(),tmpList.end(),defaultComparator);
}
// }
}
CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent)
{

View File

@ -3,6 +3,7 @@
#include <QListView>
#include <QWidget>
#include "parser/cppparser.h"
using KeyPressedCallback = std::function<bool (QKeyEvent *)>;
@ -31,9 +32,40 @@ public:
void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback);
private:
void addChildren(PStatement scopeStatement, const QString& fileName,
int line);
void addStatement(PStatement statement, const QString& fileName, int line);
void filterList(const QString& member);
void getCompletionFor(const QString& fileName,const QString& phrase, int line);
bool isIncluded(const QString& fileName);
private:
CodeCompletionListView * mListView;
QList<PCodeIns> mCodeInsList; //(Code template list)
//QList<PStatement> mCodeInsStatements; //temporary (user code template) statements created when show code suggestion
PCppParser mParser;
QList<PStatement> mFullCompletionStatementList;
QList<PStatement> mCompletionStatementList;
bool mEnabled;
int mShowCount;
bool mOnlyGlobals;
PStatement mCurrentStatement;
QSet<QString> mIncludedFiles;
QSet<QString> mUsings;
QString mIsIncludedCacheFileName;
bool mIsIncludedCacheResult;
QSet<QString> mAddedStatements;
bool mPreparing;
QString mPhrase;
QHash<QString,int> mSymbolUsage;
bool mRecordUsage;
bool mShowKeywords;
bool mShowCodeIns;
bool mIgnoreCase;
QRecursiveMutex mMutex;
QString mParserSerialId;
bool mSortByScope;
bool mUseCppKeyword;
};
#endif // CODECOMPLETIONVIEW_H

View File

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CodeCompletionView</class>
<widget class="QWidget" name="CodeCompletionView">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QListView" name="listView"/>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>