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 # You can redistribute this file and/or modify it under the terms of the BSD
# 3-Clause. # 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 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

View File

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

View File

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

View File

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

View File

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

View File

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