feat: 支持内置函数的自动补充(WIP);
This commit is contained in:
parent
4f4db8b5f8
commit
5686edde5b
|
@ -24,7 +24,16 @@
|
|||
|
||||
#include <QDebug>
|
||||
|
||||
/*
|
||||
* Completion only support: Internal classes, enums and methods,
|
||||
* Standard libraries and included headers,
|
||||
* global classes, enums and methods in opened codes
|
||||
*
|
||||
* If you want to make it more powerful, PR will be welcomed.
|
||||
*/
|
||||
|
||||
QAsParser::QAsParser(asIScriptEngine *engine) : asBuilder(), _engine(engine) {
|
||||
addClassCompletion(engine);
|
||||
addEnumCompletion(engine);
|
||||
addGlobalFunctionCompletion(engine);
|
||||
}
|
||||
|
@ -34,59 +43,6 @@ QAsParser::~QAsParser() {
|
|||
_headerNodes.clear();
|
||||
}
|
||||
|
||||
void QAsParser::processNode(asCScriptCode *code, asCScriptNode *raw,
|
||||
QCodeNode *node) {
|
||||
Q_ASSERT(raw && node);
|
||||
|
||||
int row = -1;
|
||||
if (code) {
|
||||
code->ConvertPosToRowCol(raw->tokenPos, &row, nullptr);
|
||||
}
|
||||
node->setLine(row);
|
||||
|
||||
QByteArray ns; // namespace
|
||||
|
||||
switch (raw->nodeType) {
|
||||
case snScript:
|
||||
break;
|
||||
case snNamespace:
|
||||
break;
|
||||
case snIdentifier: {
|
||||
auto name = QByteArray(m_code->code + raw->tokenPos, raw->tokenLength);
|
||||
node->setRole(QCodeNode::Name, name);
|
||||
|
||||
#ifdef QT_DEBUG
|
||||
qDebug() << name;
|
||||
#endif
|
||||
} break;
|
||||
case snDeclaration:
|
||||
qDebug() << QByteArray(m_code->code + raw->tokenPos, raw->tokenLength);
|
||||
break;
|
||||
case snImport:
|
||||
case snEnum:
|
||||
case snTypedef:
|
||||
case snClass:
|
||||
case snMixin:
|
||||
case snInterface:
|
||||
case snFuncDef:
|
||||
case snVirtualProperty:
|
||||
case snVariableAccess:
|
||||
case snFunction:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto p = raw->firstChild;
|
||||
while (p) {
|
||||
auto cnode = new QCodeNode;
|
||||
// cnode->parent = node;
|
||||
processNode(code, p, cnode);
|
||||
node->children().append(cnode);
|
||||
p = p->next;
|
||||
}
|
||||
node->children().append(node);
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnParamDeclString(asIScriptFunction *fn,
|
||||
bool includeNamespace,
|
||||
bool includeParamNames) {
|
||||
|
@ -158,6 +114,33 @@ QByteArray QAsParser::getFnParamDeclString(asIScriptFunction *fn,
|
|||
return QByteArray(str.AddressOf(), str.GetLength());
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnRealName(asIScriptFunction *fn) {
|
||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||
if (fun == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
asCString str;
|
||||
asCString name = fun->GetName();
|
||||
|
||||
if (name.GetLength() == 0)
|
||||
str += "_unnamed_function_";
|
||||
else if (name.SubString(0, 4) == "$beh" && name.GetLength() == 5) {
|
||||
if (name[4] == '0' + asBEHAVE_CONSTRUCT)
|
||||
str += fun->objectType->name;
|
||||
else if (name[4] == '0' + asBEHAVE_FACTORY)
|
||||
str += fun->returnType.GetTypeInfo()->name;
|
||||
else if (name[4] == '0' + asBEHAVE_DESTRUCT)
|
||||
str += "~" + fun->objectType->name;
|
||||
else
|
||||
str += name;
|
||||
} else {
|
||||
str = name;
|
||||
}
|
||||
|
||||
return QByteArray(str.AddressOf(), str.GetLength());
|
||||
}
|
||||
|
||||
QByteArray QAsParser::getFnRetTypeString(asIScriptFunction *fn,
|
||||
bool includeNamespace) {
|
||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||
|
@ -236,13 +219,6 @@ const QList<QCodeNode *> &QAsParser::headerNodes() const {
|
|||
void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
struct FnInfo {
|
||||
QByteArray retType;
|
||||
QByteArray fnName;
|
||||
QByteArray params;
|
||||
bool isConst = false;
|
||||
};
|
||||
|
||||
QHash<QByteArray, QList<FnInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetGlobalFunctionCount(); ++i) {
|
||||
|
@ -291,11 +267,6 @@ void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
|||
void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
struct EnumInfo {
|
||||
QByteArray name;
|
||||
QList<QPair<QByteArray, int>> enums;
|
||||
};
|
||||
|
||||
QHash<QByteArray, QList<EnumInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetEnumCount(); ++i) {
|
||||
|
@ -329,52 +300,110 @@ void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
|||
|
||||
auto pnodes = &node->children();
|
||||
auto nodeParent = node;
|
||||
for (auto &fn : p->second) {
|
||||
for (auto &e : p->second) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Enum);
|
||||
node->setRole(QCodeNode::Name, e.name);
|
||||
node->setParent(nodeParent);
|
||||
pnodes->append(node);
|
||||
|
||||
auto enode = new QCodeNode;
|
||||
_headerNodes << enode;
|
||||
enode->setNodeType(QCodeNode::Enum);
|
||||
enode->setRole(QCodeNode::Name, e.name);
|
||||
for (auto &ev : e.enums) {
|
||||
auto node = new QCodeNode;
|
||||
node->setNodeType(QCodeNode::Enumerator);
|
||||
node->setRole(QCodeNode::Name, ev.first);
|
||||
QByteArray value;
|
||||
value.setNum(ev.second);
|
||||
node->setRole(QCodeNode::Value, value);
|
||||
node->setParent(enode);
|
||||
enode->children().append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QAsParser::addClassCompletion(asIScriptEngine *engine) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
struct ClassInfo {
|
||||
QByteArray name;
|
||||
//
|
||||
};
|
||||
auto eng = dynamic_cast<asCScriptEngine *>(engine);
|
||||
Q_ASSERT(eng);
|
||||
|
||||
QHash<QByteArray, QList<ClassInfo>> _maps;
|
||||
|
||||
for (asUINT i = 0; i < engine->GetObjectTypeCount(); ++i) {
|
||||
auto obj = engine->GetObjectTypeByIndex(i);
|
||||
auto obj = eng->registeredObjTypes[i];
|
||||
obj->AddRef();
|
||||
|
||||
ClassInfo cls;
|
||||
cls.name = obj->GetNamespace();
|
||||
cls.name = obj->GetName();
|
||||
auto ns = obj->GetNamespace();
|
||||
|
||||
for (asUINT i = 0; i < obj->GetBehaviourCount(); ++i) {
|
||||
asEBehaviours bv;
|
||||
auto b = obj->GetBehaviourByIndex(i, &bv);
|
||||
|
||||
switch (bv) {
|
||||
case asBEHAVE_CONSTRUCT:
|
||||
case asBEHAVE_DESTRUCT:
|
||||
case asBEHAVE_DESTRUCT: {
|
||||
// only these are supported
|
||||
|
||||
b->AddRef();
|
||||
FnInfo fn;
|
||||
fn.fnName = getFnRealName(b);
|
||||
fn.params = getFnParamDeclString(b, false, true);
|
||||
fn.isConst = b->IsReadOnly();
|
||||
cls.methods << fn;
|
||||
b->Release();
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (asUINT i = 0; i < obj->GetMethodCount(); ++i) {
|
||||
auto m = obj->GetMethodByIndex(i);
|
||||
auto m = obj->GetMethodByIndex(i, true);
|
||||
|
||||
m->AddRef();
|
||||
FnInfo fn;
|
||||
fn.retType = getFnRetTypeString(m, true);
|
||||
fn.fnName = getFnRealName(m);
|
||||
fn.params = getFnParamDeclString(m, false, true);
|
||||
fn.isConst = m->IsReadOnly();
|
||||
cls.methods << fn;
|
||||
m->Release();
|
||||
}
|
||||
|
||||
for (asUINT i = 0; i < obj->GetPropertyCount(); ++i) {
|
||||
auto p = obj->properties[i];
|
||||
|
||||
PropertyInfo pi;
|
||||
pi.name = QByteArray(p->name.AddressOf(), p->name.GetLength());
|
||||
auto tn = p->type.Format(obj->nameSpace);
|
||||
pi.type = QByteArray(tn.AddressOf(), tn.GetLength());
|
||||
pi.isPrivate = pi.isPrivate;
|
||||
pi.isProtected = pi.isProtected;
|
||||
pi.isRef = pi.isRef;
|
||||
|
||||
cls.properties << pi;
|
||||
}
|
||||
|
||||
obj->Release();
|
||||
|
||||
_maps[ns] << cls;
|
||||
}
|
||||
|
||||
for (auto p = _maps.keyValueBegin(); p != _maps.keyValueEnd(); p++) {
|
||||
auto node = new QCodeNode;
|
||||
_headerNodes << node;
|
||||
if (p->first.isEmpty()) {
|
||||
node->setNodeType(QCodeNode::Group);
|
||||
} else {
|
||||
node->setNodeType(QCodeNode::Namespace);
|
||||
}
|
||||
node->setRole(QCodeNode::Name, p->first);
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
QList<QCodeNode *> QAsParser::codeNodes() const { return _nodes; }
|
||||
|
|
|
@ -32,12 +32,39 @@ public:
|
|||
virtual ~QAsParser();
|
||||
|
||||
private:
|
||||
void processNode(asCScriptCode *code, asCScriptNode *raw, QCodeNode *node);
|
||||
struct FnInfo {
|
||||
QByteArray retType;
|
||||
QByteArray fnName;
|
||||
QByteArray params;
|
||||
bool isConst = false;
|
||||
};
|
||||
|
||||
struct EnumInfo {
|
||||
QByteArray name;
|
||||
QList<QPair<QByteArray, int>> enums;
|
||||
};
|
||||
|
||||
struct PropertyInfo {
|
||||
QByteArray name;
|
||||
QByteArray type;
|
||||
bool isProtected = false;
|
||||
bool isPrivate = false;
|
||||
bool isRef = false;
|
||||
};
|
||||
|
||||
struct ClassInfo {
|
||||
QByteArray name;
|
||||
QList<FnInfo> methods;
|
||||
QList<PropertyInfo> properties;
|
||||
};
|
||||
|
||||
private:
|
||||
QByteArray getFnParamDeclString(asIScriptFunction *fn,
|
||||
bool includeNamespace,
|
||||
bool includeParamNames);
|
||||
|
||||
QByteArray getFnRealName(asIScriptFunction *fn);
|
||||
|
||||
QByteArray getFnRetTypeString(asIScriptFunction *fn, bool includeNamespace);
|
||||
|
||||
public:
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
|
|
|
@ -1,20 +1,3 @@
|
|||
/*==============================================================================
|
||||
** Copyright (C) 2024-2027 WingSummer
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify it under
|
||||
** the terms of the GNU Affero General Public License as published by the Free
|
||||
** Software Foundation, version 3.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
** FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
** details.
|
||||
**
|
||||
** You should have received a copy of the GNU Affero General Public License
|
||||
** along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||
|
|
Loading…
Reference in New Issue