work save
This commit is contained in:
parent
74f2d689d6
commit
ea77b45661
|
@ -139,7 +139,6 @@ HEADERS += \
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
settingsdialog/debuggeneralwidget.ui \
|
settingsdialog/debuggeneralwidget.ui \
|
||||||
widgets/codecompletionview.ui \
|
|
||||||
widgets/cpudialog.ui \
|
widgets/cpudialog.ui \
|
||||||
mainwindow.ui \
|
mainwindow.ui \
|
||||||
settingsdialog/compilersetdirectorieswidget.ui \
|
settingsdialog/compilersetdirectorieswidget.ui \
|
||||||
|
|
|
@ -3525,6 +3525,11 @@ void CppParser::updateSerialId()
|
||||||
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
|
mSerialId = QString("%1 %2").arg(mParserId).arg(mSerialCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const StatementModel &CppParser::statementList() const
|
||||||
|
{
|
||||||
|
return mStatementList;
|
||||||
|
}
|
||||||
|
|
||||||
bool CppParser::parseGlobalHeaders() const
|
bool CppParser::parseGlobalHeaders() const
|
||||||
{
|
{
|
||||||
return mParseGlobalHeaders;
|
return mParseGlobalHeaders;
|
||||||
|
|
|
@ -119,6 +119,8 @@ public:
|
||||||
bool parseGlobalHeaders() const;
|
bool parseGlobalHeaders() const;
|
||||||
void setParseGlobalHeaders(bool newParseGlobalHeaders);
|
void setParseGlobalHeaders(bool newParseGlobalHeaders);
|
||||||
|
|
||||||
|
const StatementModel &statementList() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void onProgress(const QString& fileName, int total, int current);
|
void onProgress(const QString& fileName, int total, int current);
|
||||||
void onBusy();
|
void onBusy();
|
||||||
|
|
|
@ -4,6 +4,17 @@
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <memory>
|
#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
|
// preprocess/ macro define
|
||||||
struct Define {
|
struct Define {
|
||||||
QString name;
|
QString name;
|
||||||
|
@ -190,4 +201,5 @@ bool isSystemHeaderFile(const QString& fileName, const QSet<QString>& includePat
|
||||||
bool isHfile(const QString filename);
|
bool isHfile(const QString filename);
|
||||||
bool isCfile(const QString filename);
|
bool isCfile(const QString filename);
|
||||||
bool isKeyword(const QString& word);
|
bool isKeyword(const QString& word);
|
||||||
|
|
||||||
#endif // PARSER_UTILS_H
|
#endif // PARSER_UTILS_H
|
||||||
|
|
|
@ -37,7 +37,7 @@ void StatementModel::deleteStatement(PStatement statement)
|
||||||
mCount -= count;
|
mCount -= count;
|
||||||
}
|
}
|
||||||
|
|
||||||
const StatementMap &StatementModel::childrenStatements(PStatement statement)
|
const StatementMap &StatementModel::childrenStatements(PStatement statement) const
|
||||||
{
|
{
|
||||||
if (!statement) {
|
if (!statement) {
|
||||||
return mGlobalStatements;
|
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();
|
PStatement s = statement.lock();
|
||||||
return childrenStatements(s);
|
return childrenStatements(s);
|
||||||
|
|
|
@ -15,8 +15,8 @@ public:
|
||||||
// function DeleteFirst: Integer;
|
// function DeleteFirst: Integer;
|
||||||
// function DeleteLast: Integer;
|
// function DeleteLast: Integer;
|
||||||
void deleteStatement(PStatement statement);
|
void deleteStatement(PStatement statement);
|
||||||
const StatementMap& childrenStatements(PStatement statement = PStatement());
|
const StatementMap& childrenStatements(PStatement statement = PStatement()) const;
|
||||||
const StatementMap& childrenStatements(std::weak_ptr<Statement> statement);
|
const StatementMap& childrenStatements(std::weak_ptr<Statement> statement) const;
|
||||||
void clear();
|
void clear();
|
||||||
void dump(const QString& logFile);
|
void dump(const QString& logFile);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
#include "codecompletionview.h"
|
#include "codecompletionview.h"
|
||||||
#include "ui_codecompletionview.h"
|
#include "../utils.h"
|
||||||
|
|
||||||
#include <QKeyEvent>
|
#include <QKeyEvent>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
CodeCompletionView::CodeCompletionView(QWidget *parent) :
|
CodeCompletionView::CodeCompletionView(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent)
|
||||||
|
@ -23,6 +24,257 @@ void CodeCompletionView::setKeypressedCallback(const KeyPressedCallback &newKeyp
|
||||||
mListView->setKeypressedCallback(newKeypressedCallback);
|
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)
|
CodeCompletionListView::CodeCompletionListView(QWidget *parent) : QListView(parent)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <QListView>
|
#include <QListView>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include "parser/cppparser.h"
|
||||||
|
|
||||||
using KeyPressedCallback = std::function<bool (QKeyEvent *)>;
|
using KeyPressedCallback = std::function<bool (QKeyEvent *)>;
|
||||||
|
|
||||||
|
@ -31,9 +32,40 @@ public:
|
||||||
|
|
||||||
void setKeypressedCallback(const KeyPressedCallback &newKeypressedCallback);
|
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:
|
private:
|
||||||
CodeCompletionListView * mListView;
|
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
|
#endif // CODECOMPLETIONVIEW_H
|
||||||
|
|
|
@ -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>
|
|
Loading…
Reference in New Issue