work save
This commit is contained in:
parent
74f2d689d6
commit
ea77b45661
|
@ -139,7 +139,6 @@ HEADERS += \
|
|||
|
||||
FORMS += \
|
||||
settingsdialog/debuggeneralwidget.ui \
|
||||
widgets/codecompletionview.ui \
|
||||
widgets/cpudialog.ui \
|
||||
mainwindow.ui \
|
||||
settingsdialog/compilersetdirectorieswidget.ui \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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