feat: 支持内置函数的自动补充(WIP);
This commit is contained in:
parent
4f4db8b5f8
commit
5686edde5b
|
@ -24,7 +24,16 @@
|
||||||
|
|
||||||
#include <QDebug>
|
#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) {
|
QAsParser::QAsParser(asIScriptEngine *engine) : asBuilder(), _engine(engine) {
|
||||||
|
addClassCompletion(engine);
|
||||||
addEnumCompletion(engine);
|
addEnumCompletion(engine);
|
||||||
addGlobalFunctionCompletion(engine);
|
addGlobalFunctionCompletion(engine);
|
||||||
}
|
}
|
||||||
|
@ -34,59 +43,6 @@ QAsParser::~QAsParser() {
|
||||||
_headerNodes.clear();
|
_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,
|
QByteArray QAsParser::getFnParamDeclString(asIScriptFunction *fn,
|
||||||
bool includeNamespace,
|
bool includeNamespace,
|
||||||
bool includeParamNames) {
|
bool includeParamNames) {
|
||||||
|
@ -158,6 +114,33 @@ QByteArray QAsParser::getFnParamDeclString(asIScriptFunction *fn,
|
||||||
return QByteArray(str.AddressOf(), str.GetLength());
|
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,
|
QByteArray QAsParser::getFnRetTypeString(asIScriptFunction *fn,
|
||||||
bool includeNamespace) {
|
bool includeNamespace) {
|
||||||
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
auto fun = dynamic_cast<asCScriptFunction *>(fn);
|
||||||
|
@ -236,13 +219,6 @@ const QList<QCodeNode *> &QAsParser::headerNodes() const {
|
||||||
void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
||||||
Q_ASSERT(engine);
|
Q_ASSERT(engine);
|
||||||
|
|
||||||
struct FnInfo {
|
|
||||||
QByteArray retType;
|
|
||||||
QByteArray fnName;
|
|
||||||
QByteArray params;
|
|
||||||
bool isConst = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
QHash<QByteArray, QList<FnInfo>> _maps;
|
QHash<QByteArray, QList<FnInfo>> _maps;
|
||||||
|
|
||||||
for (asUINT i = 0; i < engine->GetGlobalFunctionCount(); ++i) {
|
for (asUINT i = 0; i < engine->GetGlobalFunctionCount(); ++i) {
|
||||||
|
@ -291,11 +267,6 @@ void QAsParser::addGlobalFunctionCompletion(asIScriptEngine *engine) {
|
||||||
void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
||||||
Q_ASSERT(engine);
|
Q_ASSERT(engine);
|
||||||
|
|
||||||
struct EnumInfo {
|
|
||||||
QByteArray name;
|
|
||||||
QList<QPair<QByteArray, int>> enums;
|
|
||||||
};
|
|
||||||
|
|
||||||
QHash<QByteArray, QList<EnumInfo>> _maps;
|
QHash<QByteArray, QList<EnumInfo>> _maps;
|
||||||
|
|
||||||
for (asUINT i = 0; i < engine->GetEnumCount(); ++i) {
|
for (asUINT i = 0; i < engine->GetEnumCount(); ++i) {
|
||||||
|
@ -329,52 +300,110 @@ void QAsParser::addEnumCompletion(asIScriptEngine *engine) {
|
||||||
|
|
||||||
auto pnodes = &node->children();
|
auto pnodes = &node->children();
|
||||||
auto nodeParent = node;
|
auto nodeParent = node;
|
||||||
for (auto &fn : p->second) {
|
for (auto &e : p->second) {
|
||||||
auto node = new QCodeNode;
|
auto node = new QCodeNode;
|
||||||
node->setNodeType(QCodeNode::Enum);
|
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) {
|
void QAsParser::addClassCompletion(asIScriptEngine *engine) {
|
||||||
Q_ASSERT(engine);
|
auto eng = dynamic_cast<asCScriptEngine *>(engine);
|
||||||
|
Q_ASSERT(eng);
|
||||||
struct ClassInfo {
|
|
||||||
QByteArray name;
|
|
||||||
//
|
|
||||||
};
|
|
||||||
|
|
||||||
QHash<QByteArray, QList<ClassInfo>> _maps;
|
QHash<QByteArray, QList<ClassInfo>> _maps;
|
||||||
|
|
||||||
for (asUINT i = 0; i < engine->GetObjectTypeCount(); ++i) {
|
for (asUINT i = 0; i < engine->GetObjectTypeCount(); ++i) {
|
||||||
auto obj = engine->GetObjectTypeByIndex(i);
|
auto obj = eng->registeredObjTypes[i];
|
||||||
obj->AddRef();
|
obj->AddRef();
|
||||||
|
|
||||||
ClassInfo cls;
|
ClassInfo cls;
|
||||||
cls.name = obj->GetNamespace();
|
cls.name = obj->GetName();
|
||||||
auto ns = obj->GetNamespace();
|
auto ns = obj->GetNamespace();
|
||||||
|
|
||||||
for (asUINT i = 0; i < obj->GetBehaviourCount(); ++i) {
|
for (asUINT i = 0; i < obj->GetBehaviourCount(); ++i) {
|
||||||
asEBehaviours bv;
|
asEBehaviours bv;
|
||||||
auto b = obj->GetBehaviourByIndex(i, &bv);
|
auto b = obj->GetBehaviourByIndex(i, &bv);
|
||||||
|
|
||||||
switch (bv) {
|
switch (bv) {
|
||||||
case asBEHAVE_CONSTRUCT:
|
case asBEHAVE_CONSTRUCT:
|
||||||
case asBEHAVE_DESTRUCT:
|
case asBEHAVE_DESTRUCT: {
|
||||||
// only these are supported
|
// 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:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (asUINT i = 0; i < obj->GetMethodCount(); ++i) {
|
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();
|
obj->Release();
|
||||||
|
|
||||||
_maps[ns] << cls;
|
_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; }
|
QList<QCodeNode *> QAsParser::codeNodes() const { return _nodes; }
|
||||||
|
|
|
@ -32,12 +32,39 @@ public:
|
||||||
virtual ~QAsParser();
|
virtual ~QAsParser();
|
||||||
|
|
||||||
private:
|
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,
|
QByteArray getFnParamDeclString(asIScriptFunction *fn,
|
||||||
bool includeNamespace,
|
bool includeNamespace,
|
||||||
bool includeParamNames);
|
bool includeParamNames);
|
||||||
|
|
||||||
|
QByteArray getFnRealName(asIScriptFunction *fn);
|
||||||
|
|
||||||
QByteArray getFnRetTypeString(asIScriptFunction *fn, bool includeNamespace);
|
QByteArray getFnRetTypeString(asIScriptFunction *fn, bool includeNamespace);
|
||||||
|
|
||||||
public:
|
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>
|
** 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>
|
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
|
||||||
|
|
Loading…
Reference in New Issue