- implement: symbol usage count

work save: code snippets
This commit is contained in:
royqh1979 2021-09-30 11:20:43 +08:00
parent 9b87d93b72
commit b518304f56
17 changed files with 323 additions and 22 deletions

View File

@ -13,8 +13,9 @@ Version 0.2.2
- fix: can't coorectly show code completion for array elements
- enhancement: show caret when show code/header completions
- fix: correctly display pointer info in watch console
- enhancement: search in project
- implement: search in project
- enhancement: view memory when debugging
- implement: symbol usage count
Version 0.2.1
- fix: crash when load last opens

View File

@ -18,6 +18,7 @@ SOURCES += \
autolinkmanager.cpp \
caretlist.cpp \
codeformatter.cpp \
codesnippetsmanager.cpp \
codetemplate.cpp \
colorscheme.cpp \
compiler/projectcompiler.cpp \
@ -57,6 +58,7 @@ SOURCES += \
settingsdialog/projectoutputwidget.cpp \
settingsdialog/projectprecompilewidget.cpp \
settingsdialog/projectversioninfowidget.cpp \
symbolusagemanager.cpp \
widgets/classbrowser.cpp \
widgets/codecompletionlistview.cpp \
widgets/codecompletionpopup.cpp \
@ -117,6 +119,7 @@ HEADERS += \
autolinkmanager.h \
caretlist.h \
codeformatter.h \
codesnippetsmanager.h \
codetemplate.h \
colorscheme.h \
compiler/compiler.h \
@ -155,6 +158,7 @@ HEADERS += \
settingsdialog/projectoutputwidget.h \
settingsdialog/projectprecompilewidget.h \
settingsdialog/projectversioninfowidget.h \
symbolusagemanager.h \
widgets/classbrowser.h \
widgets/codecompletionlistview.h \
widgets/codecompletionpopup.h \

View File

@ -0,0 +1,109 @@
#include "codesnippetsmanager.h"
#include "settings.h"
#include "systemconsts.h"
#include <QMessageBox>
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
CodeSnippetsManager::CodeSnippetsManager(QObject *parent) : QObject(parent)
{
}
void CodeSnippetsManager::load()
{
//if config file not exists, copy it from data
//read config file
}
void CodeSnippetsManager::save()
{
QString filename = pSettings->dirs().config() + DEV_CODESNIPPET_FILE;
QFile file(filename);
if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
QMessageBox::critical(nullptr,
tr("Save code snippets failed"),
tr("Can't open code snippet file '%1' for write.")
.arg(filename));
}
QJsonArray array;
foreach (const PCodeSnippet& snippet,mSnippets) {
QJsonObject object;
object["caption"]=snippet->caption;
object["prefix"]=snippet->prefix;
object["code"]=snippet->code;
object["description"]=snippet->desc;
object["section"]=snippet->section;
array.append(object);
}
QJsonDocument doc;
doc.setArray(array);
if (file.write(doc.toJson())<0) {
QMessageBox::critical(nullptr,
tr("Save code snippets failed"),
tr("Write to code snippet file '%1' failed.")
.arg(filename));
}
}
void CodeSnippetsManager::addSnippet(const QString &caption, const QString &prefix, const QString &code, const QString &description, int menuSection)
{
PCodeSnippet snippet = std::make_shared<CodeSnippet>();
snippet->caption = caption;
snippet->prefix = prefix;
snippet->code = code;
snippet->desc = description;
snippet->section = menuSection;
mSnippets.append(snippet);
}
void CodeSnippetsManager::remove(int index)
{
Q_ASSERT(index>=0 && index<mSnippets.count());
mSnippets.removeAt(index);
}
void CodeSnippetsManager::clear()
{
mSnippets.clear();
}
const QList<PCodeSnippet> &CodeSnippetsManager::snippets() const
{
return mSnippets;
}
int CodeSnippetsModel::rowCount(const QModelIndex &parent) const
{
return mSnippets.count();
}
int CodeSnippetsModel::columnCount(const QModelIndex &parent) const
{
return 4;
}
bool CodeSnippetsModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
}
QVariant CodeSnippetsModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch(section) {
case 0:
return tr("Caption");
case 1:
return tr("Completion Prefix");
case 2:
return tr("Description");
case 3:
return tr("Menu Section");
}
}
return QVariant();
}

View File

@ -0,0 +1,32 @@
#ifndef CODESNIPPETSMANAGER_H
#define CODESNIPPETSMANAGER_H
#include <QObject>
#include "parser/parserutils.h"
class CodeSnippetsManager : public QObject
{
Q_OBJECT
public:
explicit CodeSnippetsManager(QObject *parent = nullptr);
void load();
void save();
void addSnippet(
const QString& caption,
const QString& prefix,
const QString& code,
const QString& description,
int menuSection);
void remove(int index);
void clear();
const QList<PCodeSnippet> &snippets() const;
signals:
private:
QList<PCodeSnippet> mSnippets;
private:
};
#endif // CODESNIPPETSMANAGER_H

View File

@ -1900,17 +1900,13 @@ void Editor::completionInsert(bool appendFunc)
PStatement statement = mCompletionPopup->selectedStatement();
if (!statement)
return;
// if devCodeCompletion.RecordUsage and (Statement^._Kind <> skUserCodeIn) then begin
// idx:=Utils.FastIndexOf(dmMain.SymbolUsage,Statement^._FullName);
// if idx = -1 then begin
// usageCount:=1;
// dmMain.SymbolUsage.AddObject(Statement^._FullName, pointer(1))
// end else begin
// usageCount := 1 + integer(dmMain.SymbolUsage.Objects[idx]);
// dmMain.SymbolUsage.Objects[idx] := pointer( usageCount );
// end;
// Statement^._UsageCount := usageCount;
// end;
if (pSettings->codeCompletion().recordUsage()
&& statement->kind != StatementKind::skUserCodeIn) {
statement->usageCount+=1;
pMainWindow->symbolUsageManager()->updateUsage(statement->fullName,
statement->usageCount);
}
QString funcAddOn = "";

View File

@ -123,6 +123,8 @@ MainWindow::MainWindow(QWidget *parent)
connect(ui->cbMemoryAddress->lineEdit(), &QLineEdit::returnPressed,
this, &MainWindow::onDebugMemoryAddressInput);
mSymbolUsageManager = std::make_shared<SymbolUsageManager>();
mSymbolUsageManager->load();
mSearchResultTreeModel = std::make_shared<SearchResultTreeModel>(&mSearchResultModel);
mSearchResultListModel = std::make_shared<SearchResultListModel>(&mSearchResultModel);
mSearchViewDelegate = std::make_shared<SearchResultTreeViewDelegate>(mSearchResultTreeModel);
@ -2391,7 +2393,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
mCompilerManager->stopCompile();
mCompilerManager->stopRun();
mSymbolUsageManager->save();
event->accept();
return;
}
@ -3746,3 +3748,7 @@ void MainWindow::on_classBrowser_doubleClicked(const QModelIndex &index)
}
}
PSymbolUsageManager &MainWindow::symbolUsageManager()
{
return mSymbolUsageManager;
}

View File

@ -11,6 +11,7 @@
#include "widgets/headercompletionpopup.h"
#include "widgets/functiontooltipwidget.h"
#include "caretlist.h"
#include "symbolusagemanager.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
@ -113,6 +114,8 @@ public:
const std::shared_ptr<QHash<StatementKind, QColor> > &statementColors() const;
PSymbolUsageManager &symbolUsageManager();
public slots:
void onCompileLog(const QString& msg);
void onCompileIssue(PCompileIssue issue);
@ -379,6 +382,7 @@ private:
PSearchResultTreeViewDelegate mSearchViewDelegate;
ClassBrowserModel mClassBrowserModel;
std::shared_ptr<QHash<StatementKind, QColor>> mStatementColors;
PSymbolUsageManager mSymbolUsageManager;
bool mCheckSyntaxInBack;
bool mOpenClosingBottomPanel;

View File

@ -1077,7 +1077,7 @@ PStatement CppParser::addStatement(const PStatement& parent,
result->fullName = newCommand;
else
result->fullName = getFullStatementName(newCommand, parent);
result->usageCount = 0;
result->usageCount = -1;
result->freqTop = 0;
mStatementList.add(result);
if (result->kind == StatementKind::skNamespace) {

View File

@ -5,7 +5,7 @@
#include <QSet>
#include <memory>
struct CodeIns {
struct CodeSnippet {
QString caption; //Name
QString prefix; //Prefix used in code suggestion
QString code; //Code body
@ -13,7 +13,7 @@ struct CodeIns {
int section; //Section in the menu
};
using PCodeIns = std::shared_ptr<CodeIns>;
using PCodeIns = std::shared_ptr<CodeSnippet>;
// preprocess/ macro define
struct Define {

View File

@ -42,6 +42,7 @@ void EditorAutoSaveWidget::doLoad()
break;
case astAllOpennedFiles:
ui->rbAllOpennedFiles->setChecked(true);
break;
default:
ui->rbProjectFiles->setChecked(true);
}

View File

@ -1,6 +1,8 @@
#include "editorcodecompletionwidget.h"
#include "ui_editorcodecompletionwidget.h"
#include "../settings.h"
#include "../mainwindow.h"
#include "../symbolusagemanager.h"
EditorCodeCompletionWidget::EditorCodeCompletionWidget(const QString& name, const QString& group,
QWidget *parent) :
@ -56,3 +58,9 @@ void EditorCodeCompletionWidget::doSave()
pSettings->codeCompletion().save();
}
void EditorCodeCompletionWidget::on_btnClearUsageData_clicked()
{
pMainWindow->symbolUsageManager()->reset();
}

View File

@ -23,6 +23,8 @@ private:
protected:
void doLoad() override;
void doSave() override;
private slots:
void on_btnClearUsageData_clicked();
};
#endif // EDITORCODECOMPLETIONWIDGET_H

View File

@ -0,0 +1,102 @@
#include "symbolusagemanager.h"
#include "settings.h"
#include "systemconsts.h"
#include <QFile>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QMessageBox>
SymbolUsageManager::SymbolUsageManager(QObject *parent) : QObject(parent)
{
}
void SymbolUsageManager::load()
{
QString filename = includeTrailingPathDelimiter(pSettings->dirs().config())
+ DEV_SYMBOLUSAGE_FILE;
if (!fileExists(filename))
return;
QFile file(filename);
if (!file.open(QFile::ReadOnly)) {
QMessageBox::critical(nullptr,
tr("Load symbol usage info failed"),
tr("Can't open symbol usage file '%1' for read.")
.arg(filename));
}
QByteArray contents = file.readAll();
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(contents,&error);
if (error.error != QJsonParseError::NoError) {
QMessageBox::critical(nullptr,
tr("Load symbol usage info failed"),
tr("Can't parse symbol usage file '%1'.")
.arg(filename));
}
mUsages.clear();
QJsonArray array = doc.array();
foreach (const QJsonValue& val, array) {
QJsonObject obj = val.toObject();
QString fullname = obj["symbol"].toString();
int count = obj["count"].toInt();
PSymbolUsage usage = std::make_shared<SymbolUsage>();
usage->fullName = fullname;
usage->count = count;
mUsages.insert(fullname,usage);
}
}
void SymbolUsageManager::save()
{
QString filename = includeTrailingPathDelimiter(pSettings->dirs().config())
+ DEV_SYMBOLUSAGE_FILE;
QFile file(filename);
if (!file.open(QFile::WriteOnly | QFile::Truncate)) {
QMessageBox::critical(nullptr,
tr("Save symbol usage info failed"),
tr("Can't open symbol usage file '%1' for write.")
.arg(filename));
}
QJsonArray array;
foreach (const PSymbolUsage& usage,mUsages) {
QJsonObject object;
object["symbol"]=usage->fullName;
object["count"]=usage->count;
array.append(object);
}
QJsonDocument doc;
doc.setArray(array);
if (file.write(doc.toJson())<0) {
QMessageBox::critical(nullptr,
tr("Save symbol usage info failed"),
tr("Write to symbol usage file '%1' failed.")
.arg(filename));
}
}
void SymbolUsageManager::reset()
{
mUsages.clear();
save();
}
PSymbolUsage SymbolUsageManager::findUsage(const QString &fullName) const
{
return mUsages.value(fullName,PSymbolUsage());
}
void SymbolUsageManager::updateUsage(const QString &symbol, int count)
{
PSymbolUsage usage = mUsages.value(symbol,PSymbolUsage());
if (usage) {
usage->count = count;
} else {
usage = std::make_shared<SymbolUsage>();
usage->fullName = symbol;
usage->count = count;
mUsages.insert(symbol,usage);
}
}

View File

@ -0,0 +1,32 @@
#ifndef SYMBOLUSAGEMANAGER_H
#define SYMBOLUSAGEMANAGER_H
#include <QObject>
#include <memory>
#include <QHash>
#include <QString>
struct SymbolUsage {
QString fullName;
int count;
};
using PSymbolUsage = std::shared_ptr<SymbolUsage>;
class SymbolUsageManager : public QObject
{
Q_OBJECT
public:
explicit SymbolUsageManager(QObject *parent = nullptr);
void load();
void save();
void reset();
PSymbolUsage findUsage(const QString& fullName) const;
void updateUsage(const QString& symbol, int count);
signals:
private:
QHash<QString, PSymbolUsage> mUsages;
};
using PSymbolUsageManager = std::shared_ptr<SymbolUsageManager>;
#endif // SYMBOLUSAGEMANAGER_H

View File

@ -32,7 +32,8 @@
#define TEMPLATE_EXT "template"
#define DEV_INTERNAL_OPEN "$__DEV_INTERNAL_OPEN"
#define DEV_LASTOPENS_FILE "lastopens.ini"
#define DEV_SYMBOLUSAGE_FILE "symbolusage.json"
#define DEV_CODESNIPPET_FILE "codesnippets.json"
#ifdef Q_OS_WIN
# define PATH_SENSITIVITY Qt::CaseInsensitive
# define PATH_SEPARATOR ";"

View File

@ -3,6 +3,7 @@
#include "../mainwindow.h"
#include "../editor.h"
#include "../editorlist.h"
#include "../symbolusagemanager.h"
#include <QKeyEvent>
#include <QVBoxLayout>
@ -360,10 +361,13 @@ void CodeCompletionPopup::filterList(const QString &member)
int thirdCount = 0;
int usageCount;
foreach (const PStatement& statement,mCompletionStatementList) {
if (statement->usageCount == 0) {
usageCount = mSymbolUsage.value(statement->fullName,0);
if (usageCount == 0)
continue;
if (statement->usageCount == -1) {
PSymbolUsage usage = pMainWindow->symbolUsageManager()->findUsage(statement->fullName);
if (usage) {
usageCount = usage->count;
} else {
usageCount = 0;
}
statement->usageCount = usageCount;
} else
usageCount = statement->usageCount;

View File

@ -85,7 +85,6 @@ private:
QSet<QString> mUsings;
QSet<QString> mAddedStatements;
QString mPhrase;
QHash<QString,int> mSymbolUsage;
QRecursiveMutex mMutex;
std::shared_ptr<QHash<StatementKind, QColor>> mColors;