feat: 更好的代码填充;

This commit is contained in:
寂静的羽夏 2025-04-12 18:50:47 +08:00
parent f51630c6f0
commit f87c0970be
8 changed files with 435 additions and 405 deletions

View File

@ -4,7 +4,7 @@
# You can redistribute this file and/or modify it under the terms of the BSD
# 3-Clause.
#
# THIS FILE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND
# THIS FILE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

View File

@ -64,8 +64,10 @@ AsCompletion::AsCompletion(WingCodeEdit *p)
AsCompletion::~AsCompletion() {}
void AsCompletion::applyEmptyNsNode(QList<CodeInfoTip> &nodes) {
void AsCompletion::applyEmptyNsNode(QList<CodeInfoTip> &nodes,
const QList<CodeInfoTip> &docNodes) {
static QList<CodeInfoTip> emptyNsNodes;
if (emptyNsNodes.isEmpty()) {
auto &hn = parser.headerNodes();
for (auto p = hn.constKeyValueBegin(); p != hn.constKeyValueEnd();
@ -81,6 +83,24 @@ void AsCompletion::applyEmptyNsNode(QList<CodeInfoTip> &nodes) {
}
emptyNsNodes.append(parser.keywordNodes());
}
nodes.clear();
for (auto &p : docNodes) {
if (p.nameSpace.isEmpty()) {
nodes.append(p);
} else {
if (p.dontAddGlobal) {
continue;
}
CodeInfoTip tip;
tip.type = CodeInfoTip::Type::Group;
tip.name = p.nameSpace;
nodes.append(tip);
}
}
nodes.append(emptyNsNodes);
}
@ -134,9 +154,10 @@ void AsCompletion::processTrigger(const QString &trigger,
auto code = content.toUtf8();
QList<CodeInfoTip> nodes;
QList<CodeInfoTip> docNodes;
if (m_parseDocument) {
nodes.append(parseDocument());
docNodes = parseDocument();
}
if (!trigger.isEmpty() && trigger != *DOT_TRIGGER) {
@ -213,7 +234,7 @@ void AsCompletion::processTrigger(const QString &trigger,
prefix = etoken.content;
tokens.removeLast();
if (tokens.isEmpty()) {
applyEmptyNsNode(nodes);
applyEmptyNsNode(nodes, docNodes);
} else {
etoken = tokens.back(); // checking later
}
@ -231,7 +252,7 @@ void AsCompletion::processTrigger(const QString &trigger,
setCompletionPrefix(prefix);
return;
} else {
applyEmptyNsNode(nodes);
applyEmptyNsNode(nodes, docNodes);
}
} else if (etoken.type != asTC_IDENTIFIER) {
popup()->hide();
@ -251,7 +272,14 @@ void AsCompletion::processTrigger(const QString &trigger,
return;
}
}
nodes = parser.headerNodes().value(ns);
nodes = parser.headerNodes().value(ns) +
parser.enumsNodes().value(ns);
for (auto &n : docNodes) {
if (n.nameSpace == ns) {
nodes.append(n);
}
}
if (nodes.isEmpty()) {
return;
}
@ -272,9 +300,11 @@ void AsCompletion::processTrigger(const QString &trigger,
return;
}
}
nodes = parser.headerNodes().value(ns);
if (nodes.isEmpty()) {
applyEmptyNsNode(nodes);
applyEmptyNsNode(nodes, docNodes);
}
}
}
@ -291,9 +321,10 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
}
auto code = editor->toPlainText();
auto engine = ScriptMachine::instance().engine();
// first preprocess the code
AsPreprocesser prepc(ScriptMachine::instance().engine());
AsPreprocesser prepc(engine);
// TODO: set include callback
// prepc.setIncludeCallback();
@ -307,7 +338,7 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
QList<CodeInfoTip> ret;
for (auto &d : data) {
QAsCodeParser parser(ScriptMachine::instance().engine());
QAsCodeParser parser(engine);
auto syms =
parser.parseAndIntell(editor->textCursor().position(), d.script);
@ -326,12 +357,28 @@ QList<CodeInfoTip> AsCompletion::parseDocument() {
break;
case QAsCodeParser::SymbolType::Enum:
tip.type = CodeInfoTip::Type::Enum;
for (auto &e : sym.children) {
CodeInfoTip en;
en.dontAddGlobal = true;
en.name = e.name;
en.nameSpace = QString::fromUtf8(e.scope.join("::"));
en.type = CodeInfoTip::Type::Enumerater;
if (!e.additonalInfo.isEmpty()) {
en.addinfo.insert(CodeInfoTip::Comment,
en.name + QStringLiteral(" = ") +
e.additonalInfo);
}
ret.append(en);
}
break;
case QAsCodeParser::SymbolType::TypeDef:
tip.type = CodeInfoTip::Type::KeyWord;
break;
case QAsCodeParser::SymbolType::Variable:
tip.type = CodeInfoTip::Type::Variable;
break;
case QAsCodeParser::SymbolType::Class:
case QAsCodeParser::SymbolType::TypeDef:
case QAsCodeParser::SymbolType::FnDef:
case QAsCodeParser::SymbolType::VarsDecl:
case QAsCodeParser::SymbolType::Invalid:
continue;
}

View File

@ -51,7 +51,8 @@ public:
virtual bool eventFilter(QObject *watched, QEvent *event) override;
private:
void applyEmptyNsNode(QList<CodeInfoTip> &nodes);
void applyEmptyNsNode(QList<CodeInfoTip> &nodes,
const QList<CodeInfoTip> &docNodes);
void applyClassNodes(QList<CodeInfoTip> &nodes);
private:

View File

@ -177,6 +177,10 @@ const QHash<QString, QList<CodeInfoTip>> &ASDataBase::headerNodes() const {
return _headerNodes;
}
const QHash<QString, QList<CodeInfoTip>> &ASDataBase::enumsNodes() const {
return _enumsNodes;
}
void ASDataBase::addGlobalFunctionCompletion(asIScriptEngine *engine) {
Q_ASSERT(engine);
@ -210,6 +214,13 @@ void ASDataBase::addEnumCompletion(asIScriptEngine *engine) {
einfo.name = etype->GetName();
einfo.type = CodeInfoTip::Type::Enum;
auto ens = einfo.nameSpace;
if (ens.isEmpty()) {
ens = einfo.name;
} else {
ens += QStringLiteral("::") + einfo.name;
}
for (asUINT i = 0; i < etype->GetEnumValueCount(); ++i) {
int v;
auto e = etype->GetEnumValueByIndex(i, &v);
@ -221,6 +232,7 @@ void ASDataBase::addEnumCompletion(asIScriptEngine *engine) {
QStringLiteral(" = ") +
QString::number(v));
einfo.children.append(en);
_enumsNodes[ens].append(en);
}
etype->Release();

View File

@ -42,6 +42,7 @@ private:
public:
const QHash<QString, QList<CodeInfoTip>> &headerNodes() const;
const QHash<QString, QList<CodeInfoTip>> &enumsNodes() const;
const QList<CodeInfoTip> &keywordNodes() const;
@ -55,6 +56,7 @@ private:
private:
// <namespace, content>
QHash<QString, QList<CodeInfoTip>> _headerNodes;
QHash<QString, QList<CodeInfoTip>> _enumsNodes;
QList<CodeInfoTip> _keywordNode;
};

View File

@ -78,6 +78,7 @@ public:
public:
QString name;
bool dontAddGlobal = false;
Type type = Type::Unknown;
QString nameSpace;
CodeInfoVisibility visualpo = CodeInfoVisibility::VISIBILITY_DEFAULT;

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,6 @@ public:
Function, // a function
TypeDef, // a typedef
FnDef, // a funcdef
VarsDecl, // global variable decalration
};
enum class Visiblity { Public, Private, Protected };
@ -57,22 +56,34 @@ public:
*/
struct CodeSegment {
QByteArrayList scope;
QString name;
QByteArray name;
SymbolType type = QAsCodeParser::SymbolType::Invalid;
int offset = -1;
QString codes;
qsizetype offset = -1;
QByteArray codes;
QByteArrayList additonalInfos; // for other additonal infos
public:
bool isValid() const { return type != SymbolType::Invalid; }
bool hasCodes() const { return !codes.isEmpty(); }
inline bool isValid() const {
return offset >= 0 && type != SymbolType::Invalid;
}
inline qsizetype end() const {
if (offset < 0) {
return -1;
}
return offset + codes.length();
}
inline qsizetype length() const { return codes.length(); }
inline bool hasCodes() const { return !codes.isEmpty(); }
};
struct Symbol {
SymbolType symtype = QAsCodeParser::SymbolType::Invalid;
QByteArrayList scope;
QString name;
QByteArray name;
QByteArray type;
int offset = -1;
Visiblity vis = QAsCodeParser::Visiblity::Public;
@ -95,16 +106,15 @@ public:
private:
QList<QAsCodeParser::CodeSegment> parseScript(bool inBlock);
void appendValidSeg(QList<QAsCodeParser::CodeSegment> &container,
QAsCodeParser::CodeSegment seg);
void skipCodeBlock();
QByteArray getSymbolString(const sToken &t);
QByteArrayList getRealNamespace(const QByteArrayList &ns);
// Statements
sToken superficiallyParseVarInit();
void superficiallyParseVarInit();
sToken superficiallyParseStatementBlock();
void superficiallyParseExpression();
void superficiallyParseTemplateList();
void parseMethodAttributes();
private:
@ -131,12 +141,24 @@ private:
private:
// deep parsing
void parseStatementBlock();
void parseStatement();
QList<Symbol> parseEnumerationContent(const QByteArrayList &ns,
const QByteArray &name,
const QByteArray &code);
Symbol parseTypedefContent(const QByteArrayList &ns,
const QByteArray &code);
QList<Symbol> parseGlobalVarDecls(const QByteArrayList &ns,
const QByteArray &code);
QByteArrayList parseOptionalScope();
QList<Symbol> parseDeclaration(const QByteArrayList &ns,
bool isClassProp = false,
bool isGlobalVar = false);
private:
void parseEnumerationContent();
void parseTypedefContent();
void parseStatementBlock();
void parseStatement();
void parseClassContent();
void parseMixinContent();
void parseInterfaceContent();
@ -166,8 +188,6 @@ private:
void ParseExprPostOp();
void ParseExprValue();
QByteArrayList ParseOptionalScope();
Symbol parseVirtualPropertyDecl(bool isMethod, bool isInterface);
QList<Symbol> parseParameterListContent();
@ -192,20 +212,17 @@ private:
void getToken(sToken *token);
void rewindTo(const sToken *token);
void rewindErrorTo(sToken *token);
void SetPos(size_t pos);
void setPos(size_t pos);
bool isRealType(int tokenType);
bool isPrimType(int tokenType);
bool identifierIs(const sToken &t, const char *str);
bool isDataType(const sToken &token);
private:
bool checkTemplateType(const sToken &t);
bool parseTemplTypeList(bool required = true);
void parseArgList(bool withParenthesis = true);
void superficiallyParseExpression();
private:
bool findTokenAfterType(sToken &nextToken);
bool findIdentifierAfterScope(sToken &nextToken);
@ -219,28 +236,25 @@ private:
Symbol parseFunctionDefinition();
QList<Symbol> parseDeclaration(bool isClassProp = false,
bool isGlobalVar = false);
Symbol parseInterfaceMethod();
void ParseStringConstant();
private:
bool errorWhileParsing;
bool isSyntaxError;
bool checkValidTypes;
bool isParsingAppInterface;
bool _errorWhileParsing;
bool _isSyntaxError;
bool _checkValidTypes;
bool _isParsingAppInterface;
asCScriptEngine *engine;
// size_t _curscope = 0;
QByteArray code;
QByteArray _code;
QByteArray tempString; // Used for reduzing amount of dynamic allocations
sToken lastToken;
size_t sourcePos;
sToken _lastToken;
size_t _sourcePos;
QByteArrayList currentNs;
};