feat: 数值增加无符号切换格式;初步代码内容提示;
This commit is contained in:
parent
7ee69b5ced
commit
7597663d76
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -39,7 +39,7 @@ int asBuilder::StartNewModule(const char *moduleName) {
|
|||
if (module == nullptr)
|
||||
return -1;
|
||||
|
||||
ClearAll();
|
||||
clearAll();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ int asBuilder::Build() {
|
|||
|
||||
for (auto &mod : modifiedScripts) {
|
||||
module->AddScriptSection(mod.section.toUtf8(), mod.script.data(),
|
||||
mod.script.size(), mod.lineOffset);
|
||||
mod.script.size());
|
||||
}
|
||||
|
||||
int r = module->Build();
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include "ascompletion.h"
|
||||
|
||||
#include "asdatabase.h"
|
||||
#include "class/aspreprocesser.h"
|
||||
#include "class/qascodeparser.h"
|
||||
#include "model/codecompletionmodel.h"
|
||||
#include "wingcodeedit.h"
|
||||
|
||||
|
@ -38,8 +40,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, LEFT_PARE_TRIGGER, ("("))
|
|||
Q_GLOBAL_STATIC_WITH_ARGS(QByteArray, SEMI_COLON_TRIGGER, (";"))
|
||||
|
||||
AsCompletion::AsCompletion(asIScriptEngine *engine, WingCodeEdit *p)
|
||||
: WingCompleter(p), parser(engine), _engine(engine),
|
||||
m_parseDocument(false) {
|
||||
: WingCompleter(p), parser(engine), _engine(engine), m_parseDocument(true) {
|
||||
Q_ASSERT(engine);
|
||||
|
||||
setTriggerList({*DOT_TRIGGER, *DBL_COLON_TRIGGER,
|
||||
|
@ -80,7 +81,7 @@ void AsCompletion::applyEmptyNsNode(QList<CodeInfoTip> &nodes) {
|
|||
}
|
||||
emptyNsNodes.append(parser.keywordNodes());
|
||||
}
|
||||
nodes = emptyNsNodes;
|
||||
nodes.append(emptyNsNodes);
|
||||
}
|
||||
|
||||
void AsCompletion::applyClassNodes(QList<CodeInfoTip> &nodes) {
|
||||
|
@ -134,10 +135,6 @@ void AsCompletion::processTrigger(const QString &trigger,
|
|||
|
||||
QList<CodeInfoTip> nodes;
|
||||
|
||||
// TODO: PRs are welcomed !!!
|
||||
// If this software is well-known or brings me lots of
|
||||
// financial support, I will implement it myself.
|
||||
// PARSING THE DOCUMENT
|
||||
if (m_parseDocument) {
|
||||
nodes.append(parseDocument());
|
||||
}
|
||||
|
@ -286,7 +283,64 @@ void AsCompletion::processTrigger(const QString &trigger,
|
|||
setCompletionPrefix(prefix);
|
||||
}
|
||||
|
||||
QList<CodeInfoTip> AsCompletion::parseDocument() { return {}; }
|
||||
QList<CodeInfoTip> AsCompletion::parseDocument() {
|
||||
auto editor = qobject_cast<WingCodeEdit *>(widget());
|
||||
if (editor == nullptr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto code = editor->toPlainText();
|
||||
|
||||
// first preprocess the code
|
||||
AsPreprocesser prepc(_engine);
|
||||
// TODO: set include callback
|
||||
// prepc.setIncludeCallback();
|
||||
|
||||
auto r = prepc.loadSectionFromMemory(QStringLiteral("ASCOMPLETION"),
|
||||
code.toUtf8());
|
||||
if (r <= 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto data = prepc.scriptData();
|
||||
QList<CodeInfoTip> ret;
|
||||
|
||||
for (auto &d : data) {
|
||||
QAsCodeParser parser(_engine);
|
||||
auto syms =
|
||||
parser.parseAndIntell(editor->textCursor().position(), d.script);
|
||||
|
||||
for (auto &sym : syms) {
|
||||
CodeInfoTip tip;
|
||||
tip.name = sym.name;
|
||||
tip.nameSpace = QString::fromUtf8(sym.scope.join("::"));
|
||||
|
||||
switch (sym.symtype) {
|
||||
case QAsCodeParser::SymbolType::Function:
|
||||
tip.type = CodeInfoTip::Type::Function;
|
||||
tip.addinfo.insert(CodeInfoTip::RetType,
|
||||
QString::fromUtf8(sym.type));
|
||||
tip.addinfo.insert(CodeInfoTip::Args,
|
||||
QString::fromUtf8(sym.additonalInfo));
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::Enum:
|
||||
tip.type = CodeInfoTip::Type::Enum;
|
||||
break;
|
||||
case QAsCodeParser::SymbolType::Variable:
|
||||
case QAsCodeParser::SymbolType::Class:
|
||||
case QAsCodeParser::SymbolType::TypeDef:
|
||||
case QAsCodeParser::SymbolType::FnDef:
|
||||
case QAsCodeParser::SymbolType::VarsDecl:
|
||||
case QAsCodeParser::SymbolType::Invalid:
|
||||
continue;
|
||||
}
|
||||
|
||||
ret.append(tip);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AsCompletion::eventFilter(QObject *watched, QEvent *event) {
|
||||
if (event->type() == QEvent::KeyPress) {
|
||||
|
|
|
@ -1,12 +1,26 @@
|
|||
/*==============================================================================
|
||||
** 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/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#include "asconsolecompletion.h"
|
||||
|
||||
#include "control/scriptingconsole.h"
|
||||
|
||||
AsConsoleCompletion::AsConsoleCompletion(asIScriptEngine *engine,
|
||||
ScriptingConsole *p)
|
||||
: AsCompletion(engine, p), _console(p) {}
|
||||
|
||||
QList<CodeInfoTip> AsConsoleCompletion::parseDocument() {
|
||||
// TODO
|
||||
return {};
|
||||
: AsCompletion(engine, p), _console(p) {
|
||||
setParseDocument(false);
|
||||
}
|
||||
|
|
|
@ -1,3 +1,20 @@
|
|||
/*==============================================================================
|
||||
** 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/>.
|
||||
** =============================================================================
|
||||
*/
|
||||
|
||||
#ifndef ASCONSOLECOMPLETION_H
|
||||
#define ASCONSOLECOMPLETION_H
|
||||
|
||||
|
@ -11,10 +28,6 @@ public:
|
|||
explicit AsConsoleCompletion(asIScriptEngine *engine, ScriptingConsole *p);
|
||||
virtual ~AsConsoleCompletion() = default;
|
||||
|
||||
// AsCompletion interface
|
||||
protected:
|
||||
virtual QList<CodeInfoTip> parseDocument() override;
|
||||
|
||||
private:
|
||||
ScriptingConsole *_console;
|
||||
};
|
||||
|
|
|
@ -41,14 +41,14 @@ AsPreprocesser::AsPreprocesser(asIScriptEngine *engine) : engine(engine) {
|
|||
|
||||
AsPreprocesser::~AsPreprocesser() { void ClearAll(); }
|
||||
|
||||
int AsPreprocesser::AddSectionFromFile(const QString &filename) {
|
||||
int AsPreprocesser::loadSectionFromFile(const QString &filename) {
|
||||
// The file name stored in the set should be the fully resolved name because
|
||||
// it is possible to name the same file in multiple ways using relative
|
||||
// paths.
|
||||
auto fullpath = QFileInfo(filename).absoluteFilePath();
|
||||
|
||||
if (IncludeIfNotAlreadyIncluded(fullpath)) {
|
||||
int r = LoadScriptSection(fullpath);
|
||||
if (includeIfNotAlreadyIncluded(fullpath)) {
|
||||
int r = loadScriptSection(fullpath);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else
|
||||
|
@ -58,55 +58,57 @@ int AsPreprocesser::AddSectionFromFile(const QString &filename) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
QList<AsPreprocesser::ScriptData> AsPreprocesser::GetScriptData() const {
|
||||
int AsPreprocesser::loadSectionFromMemory(const QString §ion,
|
||||
const QByteArray &code) {
|
||||
int r = processScriptSection(code, section);
|
||||
if (r < 0)
|
||||
return r;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
QList<AsPreprocesser::ScriptData> AsPreprocesser::scriptData() const {
|
||||
return modifiedScripts;
|
||||
}
|
||||
|
||||
asIScriptEngine *AsPreprocesser::GetEngine() { return engine; }
|
||||
asIScriptEngine *AsPreprocesser::getEngine() { return engine; }
|
||||
|
||||
void AsPreprocesser::SetIncludeCallback(INCLUDECALLBACK_t callback,
|
||||
void AsPreprocesser::setIncludeCallback(INCLUDECALLBACK_t callback,
|
||||
void *userParam) {
|
||||
includeCallback = callback;
|
||||
includeParam = userParam;
|
||||
}
|
||||
|
||||
void AsPreprocesser::SetPragmaCallback(PRAGMACALLBACK_t callback,
|
||||
void AsPreprocesser::setPragmaCallback(PRAGMACALLBACK_t callback,
|
||||
void *userParam) {
|
||||
pragmaCallback = callback;
|
||||
pragmaParam = userParam;
|
||||
}
|
||||
|
||||
void AsPreprocesser::DefineWord(const QString &word) {
|
||||
void AsPreprocesser::defineWord(const QString &word) {
|
||||
if (!definedWords.contains(word)) {
|
||||
definedWords.append(word);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int AsPreprocesser::GetSectionCount() const {
|
||||
unsigned int AsPreprocesser::sectionCount() const {
|
||||
return (unsigned int)(includedScripts.size());
|
||||
}
|
||||
|
||||
QString AsPreprocesser::GetSectionName(unsigned int idx) const {
|
||||
QString AsPreprocesser::sectionName(unsigned int idx) const {
|
||||
if (qsizetype(idx) >= qsizetype(includedScripts.size()))
|
||||
return {};
|
||||
|
||||
return includedScripts.at(idx);
|
||||
}
|
||||
|
||||
void AsPreprocesser::ClearAll() { includedScripts.clear(); }
|
||||
void AsPreprocesser::clearAll() { includedScripts.clear(); }
|
||||
|
||||
int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
||||
const QString §ionname,
|
||||
int lineOffset) {
|
||||
int AsPreprocesser::processScriptSection(const QByteArray &script,
|
||||
const QString §ionname) {
|
||||
QVector<QPair<QString, bool>> includes;
|
||||
|
||||
QByteArray modifiedScript;
|
||||
|
||||
// Perform a superficial parsing of the script first to store the metadata
|
||||
if (length)
|
||||
modifiedScript = script.left(length);
|
||||
else
|
||||
modifiedScript = script;
|
||||
QByteArray modifiedScript = script;
|
||||
|
||||
// First perform the checks for #if directives to exclude code that
|
||||
// shouldn't be compiled
|
||||
|
@ -144,13 +146,13 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
// Overwrite the #if directive with space characters to
|
||||
// avoid compiler error
|
||||
pos += len;
|
||||
OverwriteCode(modifiedScript, start, pos - start);
|
||||
overwriteCode(modifiedScript, start, pos - start);
|
||||
|
||||
// Has this identifier been defined by the application or
|
||||
// not?
|
||||
if (!definedWords.contains(word)) {
|
||||
// Exclude all the code until and including the #endif
|
||||
pos = ExcludeCode(modifiedScript, pos);
|
||||
pos = excludeCode(modifiedScript, pos);
|
||||
} else {
|
||||
nested++;
|
||||
}
|
||||
|
@ -158,7 +160,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
} else if (token == "endif") {
|
||||
// Only remove the #endif if there was a matching #if
|
||||
if (nested > 0) {
|
||||
OverwriteCode(modifiedScript, start, pos - start);
|
||||
overwriteCode(modifiedScript, start, pos - start);
|
||||
nested--;
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +233,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
|
||||
// Overwrite the include directive with space
|
||||
// characters to avoid compiler error
|
||||
OverwriteCode(modifiedScript, start, pos - start);
|
||||
overwriteCode(modifiedScript, start, pos - start);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,7 +281,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
|
||||
// Overwrite the include directive with
|
||||
// space characters to avoid compiler error
|
||||
OverwriteCode(modifiedScript, start,
|
||||
overwriteCode(modifiedScript, start,
|
||||
pos - start);
|
||||
}
|
||||
} else {
|
||||
|
@ -305,7 +307,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
|
||||
// Overwrite the pragma directive with space characters
|
||||
// to avoid compiler error
|
||||
OverwriteCode(modifiedScript, start, pos - start);
|
||||
overwriteCode(modifiedScript, start, pos - start);
|
||||
|
||||
int r = pragmaCallback
|
||||
? pragmaCallback(pragmaText, this, sectionname,
|
||||
|
@ -324,14 +326,14 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
// Don't search for includes within statement blocks or
|
||||
// between tokens in statements
|
||||
else {
|
||||
pos = SkipStatement(modifiedScript, pos);
|
||||
pos = skipStatement(modifiedScript, pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the actual script
|
||||
engine->SetEngineProperty(asEP_COPY_SCRIPT_SECTIONS, true);
|
||||
|
||||
AddScriptSection(sectionname, modifiedScript, lineOffset);
|
||||
addScriptSection(sectionname, modifiedScript);
|
||||
|
||||
if (includes.size() > 0) {
|
||||
// If the callback has been set, then call it for each included file
|
||||
|
@ -362,7 +364,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
}
|
||||
|
||||
// Include the script section
|
||||
int r = AddSectionFromFile(includes[n].first);
|
||||
int r = loadSectionFromFile(includes[n].first);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
@ -372,7 +374,7 @@ int AsPreprocesser::ProcessScriptSection(const QByteArray &script, int length,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int AsPreprocesser::LoadScriptSection(const QString &filename) {
|
||||
int AsPreprocesser::loadScriptSection(const QString &filename) {
|
||||
// Open the script file
|
||||
|
||||
QFile f(filename);
|
||||
|
@ -396,10 +398,10 @@ int AsPreprocesser::LoadScriptSection(const QString &filename) {
|
|||
|
||||
// Process the script section even if it is zero length so that the name is
|
||||
// registered
|
||||
return ProcessScriptSection(code, code.length(), filename, 0);
|
||||
return processScriptSection(code, filename);
|
||||
}
|
||||
|
||||
bool AsPreprocesser::IncludeIfNotAlreadyIncluded(const QString &filename) {
|
||||
bool AsPreprocesser::includeIfNotAlreadyIncluded(const QString &filename) {
|
||||
if (includedScripts.contains(filename)) {
|
||||
// Already included
|
||||
return false;
|
||||
|
@ -410,7 +412,7 @@ bool AsPreprocesser::IncludeIfNotAlreadyIncluded(const QString &filename) {
|
|||
return true;
|
||||
}
|
||||
|
||||
int AsPreprocesser::SkipStatement(const QByteArray &modifiedScript, int pos) {
|
||||
int AsPreprocesser::skipStatement(const QByteArray &modifiedScript, int pos) {
|
||||
asUINT len = 0;
|
||||
|
||||
// Skip until ; or { whichever comes first
|
||||
|
@ -445,7 +447,7 @@ int AsPreprocesser::SkipStatement(const QByteArray &modifiedScript, int pos) {
|
|||
return pos;
|
||||
}
|
||||
|
||||
int AsPreprocesser::ExcludeCode(QByteArray &modifiedScript, int pos) {
|
||||
int AsPreprocesser::excludeCode(QByteArray &modifiedScript, int pos) {
|
||||
asUINT len = 0;
|
||||
int nested = 0;
|
||||
while (pos < (int)modifiedScript.size()) {
|
||||
|
@ -459,7 +461,7 @@ int AsPreprocesser::ExcludeCode(QByteArray &modifiedScript, int pos) {
|
|||
engine->ParseToken(modifiedScript.data() + pos,
|
||||
modifiedScript.size() - pos, &len);
|
||||
QString token = modifiedScript.mid(pos, len);
|
||||
OverwriteCode(modifiedScript, pos, len);
|
||||
overwriteCode(modifiedScript, pos, len);
|
||||
|
||||
if (token == "if") {
|
||||
nested++;
|
||||
|
@ -470,7 +472,7 @@ int AsPreprocesser::ExcludeCode(QByteArray &modifiedScript, int pos) {
|
|||
}
|
||||
}
|
||||
} else if (modifiedScript[pos] != '\n') {
|
||||
OverwriteCode(modifiedScript, pos, len);
|
||||
overwriteCode(modifiedScript, pos, len);
|
||||
}
|
||||
pos += len;
|
||||
}
|
||||
|
@ -478,7 +480,7 @@ int AsPreprocesser::ExcludeCode(QByteArray &modifiedScript, int pos) {
|
|||
return pos;
|
||||
}
|
||||
|
||||
void AsPreprocesser::OverwriteCode(QByteArray &modifiedScript, int start,
|
||||
void AsPreprocesser::overwriteCode(QByteArray &modifiedScript, int start,
|
||||
int len) {
|
||||
auto code = modifiedScript.data() + start;
|
||||
for (int n = 0; n < len; n++) {
|
||||
|
@ -488,11 +490,10 @@ void AsPreprocesser::OverwriteCode(QByteArray &modifiedScript, int start,
|
|||
}
|
||||
}
|
||||
|
||||
void AsPreprocesser::AddScriptSection(const QString §ion,
|
||||
const QByteArray &code, int lineOffset) {
|
||||
void AsPreprocesser::addScriptSection(const QString §ion,
|
||||
const QByteArray &code) {
|
||||
ScriptData data;
|
||||
data.section = section;
|
||||
data.lineOffset = lineOffset;
|
||||
data.script = code;
|
||||
modifiedScripts.append(data);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,6 @@ public:
|
|||
public:
|
||||
struct ScriptData {
|
||||
QString section;
|
||||
int lineOffset = -1;
|
||||
QByteArray script;
|
||||
};
|
||||
|
||||
|
@ -79,41 +78,40 @@ public:
|
|||
// Returns 1 if the file was included
|
||||
// 0 if the file had already been included before
|
||||
// <0 on error
|
||||
int AddSectionFromFile(const QString &filename);
|
||||
int loadSectionFromFile(const QString &filename);
|
||||
int loadSectionFromMemory(const QString §ion, const QByteArray &code);
|
||||
|
||||
QList<ScriptData> GetScriptData() const;
|
||||
QList<ScriptData> scriptData() const;
|
||||
|
||||
// Returns the engine
|
||||
asIScriptEngine *GetEngine();
|
||||
asIScriptEngine *getEngine();
|
||||
|
||||
// Register the callback for resolving include directive
|
||||
void SetIncludeCallback(INCLUDECALLBACK_t callback, void *userParam);
|
||||
void setIncludeCallback(INCLUDECALLBACK_t callback, void *userParam);
|
||||
|
||||
// Register the callback for resolving pragma directive
|
||||
void SetPragmaCallback(PRAGMACALLBACK_t callback, void *userParam);
|
||||
void setPragmaCallback(PRAGMACALLBACK_t callback, void *userParam);
|
||||
|
||||
// Add a pre-processor define for conditional compilation
|
||||
void DefineWord(const QString &word);
|
||||
void defineWord(const QString &word);
|
||||
|
||||
// Enumerate included script sections
|
||||
unsigned int GetSectionCount() const;
|
||||
unsigned int sectionCount() const;
|
||||
|
||||
QString GetSectionName(unsigned int idx) const;
|
||||
QString sectionName(unsigned int idx) const;
|
||||
|
||||
protected:
|
||||
void ClearAll();
|
||||
int ProcessScriptSection(const QByteArray &script, int length,
|
||||
const QString §ionname, int lineOffset);
|
||||
int LoadScriptSection(const QString &filename);
|
||||
bool IncludeIfNotAlreadyIncluded(const QString &filename);
|
||||
void clearAll();
|
||||
void addScriptSection(const QString §ion, const QByteArray &code);
|
||||
int processScriptSection(const QByteArray &script,
|
||||
const QString §ionname);
|
||||
int loadScriptSection(const QString &filename);
|
||||
bool includeIfNotAlreadyIncluded(const QString &filename);
|
||||
|
||||
int SkipStatement(const QByteArray &modifiedScript, int pos);
|
||||
int skipStatement(const QByteArray &modifiedScript, int pos);
|
||||
|
||||
int ExcludeCode(QByteArray &modifiedScript, int pos);
|
||||
void OverwriteCode(QByteArray &modifiedScript, int start, int len);
|
||||
|
||||
void AddScriptSection(const QString §ion, const QByteArray &code,
|
||||
int lineOffset);
|
||||
int excludeCode(QByteArray &modifiedScript, int pos);
|
||||
void overwriteCode(QByteArray &modifiedScript, int start, int len);
|
||||
|
||||
asIScriptEngine *engine;
|
||||
QList<ScriptData> modifiedScripts;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,8 +27,7 @@
|
|||
// This class is the modification of as_parser.
|
||||
// You can modified it to support more features.
|
||||
/** It's a complex thing to fully support AngelScript code intellisense.
|
||||
** I just support basic code completion like local or global
|
||||
* variables/functions.
|
||||
** I just support basic code completion.
|
||||
** If you are interested in implement a well-featured intellisense like
|
||||
* Qt creator or Visual Studio, PRs are welcomed !!!
|
||||
*/
|
||||
|
@ -42,101 +41,115 @@ public:
|
|||
public:
|
||||
enum class SymbolType {
|
||||
Invalid,
|
||||
FnDecl,
|
||||
Import,
|
||||
Value, // a common value
|
||||
Variable, // a variable
|
||||
Variable, // variable or property in class
|
||||
Enum, // an enum
|
||||
Class, // a class type
|
||||
Function, // a function
|
||||
TypeDef, // a typedef
|
||||
FnDef, // a funcdef
|
||||
Property, // a property
|
||||
VarsDecl, // global variable decalration
|
||||
};
|
||||
|
||||
enum class Visiblity { Public, Private, Protected };
|
||||
|
||||
struct Symbol;
|
||||
|
||||
/**
|
||||
* @brief The CodeSegment class
|
||||
*/
|
||||
struct CodeSegment {
|
||||
bool valid = false;
|
||||
// QByteArrayList ns;
|
||||
QByteArray ret;
|
||||
QByteArray name;
|
||||
qsizetype nameInSrc = -1;
|
||||
QList<Symbol> args;
|
||||
QByteArray code;
|
||||
QByteArrayList scope;
|
||||
QString name;
|
||||
SymbolType type = QAsCodeParser::SymbolType::Invalid;
|
||||
int offset = -1;
|
||||
QString codes;
|
||||
|
||||
bool isValid() const { return valid; }
|
||||
QByteArrayList additonalInfos; // for other additonal infos
|
||||
|
||||
public:
|
||||
bool isValid() const { return type != SymbolType::Invalid; }
|
||||
bool hasCodes() const { return !codes.isEmpty(); }
|
||||
};
|
||||
|
||||
struct Symbol {
|
||||
SymbolType type = SymbolType::Invalid;
|
||||
SymbolType symtype = QAsCodeParser::SymbolType::Invalid;
|
||||
QByteArrayList scope;
|
||||
QString name;
|
||||
qsizetype nameInSrc = -1;
|
||||
QString typeStr;
|
||||
Visiblity vis = Visiblity::Public;
|
||||
QList<Symbol> content;
|
||||
QByteArray type;
|
||||
int offset = -1;
|
||||
Visiblity vis = QAsCodeParser::Visiblity::Public;
|
||||
QByteArray additonalInfo; // for other additonal info
|
||||
|
||||
// QByteArrayList ns; // namespaces
|
||||
QMap<qsizetype, CodeSegment> codesegs; // used in class
|
||||
|
||||
// size_t scope = 0; // 0 for all
|
||||
|
||||
bool isValid() const { return type != SymbolType::Invalid; }
|
||||
QList<Symbol> children;
|
||||
};
|
||||
|
||||
using SymbolTable = QMap<size_t, Symbol>;
|
||||
|
||||
private:
|
||||
// QMap< offset , CodeSegment>
|
||||
QMap<qsizetype, CodeSegment> m_segs; // global functions
|
||||
|
||||
public:
|
||||
SymbolTable parse(const QByteArray &codes);
|
||||
// First, we should parse and split the code into segments
|
||||
QList<QAsCodeParser::CodeSegment> parse(const QByteArray &codes);
|
||||
|
||||
SymbolTable parseIntell(qsizetype offset, const QByteArray &codes);
|
||||
// Then, we can deep parsing for code completion
|
||||
QList<Symbol> parseIntell(qsizetype offset,
|
||||
const QList<QAsCodeParser::CodeSegment> &segs);
|
||||
|
||||
// so, a helper function?
|
||||
QList<Symbol> parseAndIntell(qsizetype offset, const QByteArray &codes);
|
||||
|
||||
private:
|
||||
void ParseScript(bool inBlock);
|
||||
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);
|
||||
|
||||
// parse tokens
|
||||
sToken ParseIdentifier();
|
||||
sToken ParseToken(int token);
|
||||
sToken ParseRealType();
|
||||
sToken ParseDataType(bool allowVariableType = false,
|
||||
bool allowAuto = false);
|
||||
sToken ParseOneOf(int *tokens, int count);
|
||||
sToken ParseType(bool allowConst, bool allowVariableType = false,
|
||||
bool allowAuto = false);
|
||||
|
||||
// Statements
|
||||
sToken SuperficiallyParseVarInit();
|
||||
sToken superficiallyParseVarInit();
|
||||
sToken superficiallyParseStatementBlock();
|
||||
void parseMethodAttributes();
|
||||
|
||||
// parse and get symbols
|
||||
Symbol ParseImport();
|
||||
void ParseEnumeration();
|
||||
void ParseTypedef();
|
||||
void ParseClass();
|
||||
void ParseMixin();
|
||||
void ParseInterface();
|
||||
Symbol ParseFuncDef();
|
||||
void ParseNamespace();
|
||||
private:
|
||||
CodeSegment parseEnumeration();
|
||||
CodeSegment parseTypedef();
|
||||
CodeSegment parseClass();
|
||||
CodeSegment parseMixin();
|
||||
CodeSegment parseInterface();
|
||||
CodeSegment parseFuncDef();
|
||||
CodeSegment parseFunction();
|
||||
|
||||
private:
|
||||
// parse tokens
|
||||
sToken parseIdentifier();
|
||||
sToken parseToken(int token);
|
||||
sToken parseRealType();
|
||||
sToken parseDataType(bool allowVariableType = false,
|
||||
bool allowAuto = false);
|
||||
sToken parseOneOf(int *tokens, int count);
|
||||
sToken parseType(bool allowConst, bool allowVariableType = false,
|
||||
bool allowAuto = false);
|
||||
|
||||
void parseNamespace();
|
||||
|
||||
private:
|
||||
// deep parsing
|
||||
void parseStatementBlock();
|
||||
void parseStatement();
|
||||
|
||||
private:
|
||||
void parseEnumerationContent();
|
||||
void parseTypedefContent();
|
||||
void parseClassContent();
|
||||
void parseMixinContent();
|
||||
void parseInterfaceContent();
|
||||
Symbol parseFuncDefContent();
|
||||
void ParseReturn();
|
||||
void ParseBreak();
|
||||
void ParseContinue();
|
||||
void ParseTryCatch();
|
||||
void ParseIf();
|
||||
void ParseLambda();
|
||||
void ParseStatement();
|
||||
CodeSegment ParseFunction(bool isMethod = false);
|
||||
CodeSegment parseFunction(bool isMethod);
|
||||
void ParseExpressionStatement();
|
||||
void ParseListPattern();
|
||||
void ParseStatementBlock();
|
||||
|
||||
void ParseAssignment();
|
||||
void ParseAssignOperator();
|
||||
|
@ -155,13 +168,12 @@ private:
|
|||
|
||||
QByteArrayList ParseOptionalScope();
|
||||
|
||||
Symbol ParseVirtualPropertyDecl(bool isMethod, bool isInterface);
|
||||
QList<Symbol> ParseParameterList();
|
||||
Symbol parseVirtualPropertyDecl(bool isMethod, bool isInterface);
|
||||
QList<Symbol> parseParameterListContent();
|
||||
|
||||
// parse but not get symbols
|
||||
void ParseTypeMod(bool isParam);
|
||||
void ParseFunctionCall();
|
||||
void SuperficiallyParseStatementBlock();
|
||||
void ParseInitList();
|
||||
void ParseCast();
|
||||
void ParseVariableAccess();
|
||||
|
@ -169,49 +181,48 @@ private:
|
|||
void ParseConstant();
|
||||
|
||||
private:
|
||||
void Reset();
|
||||
void reset();
|
||||
|
||||
bool IsVarDecl();
|
||||
bool IsVirtualPropertyDecl();
|
||||
bool IsFuncDecl(bool isMethod);
|
||||
bool IsLambda();
|
||||
bool IsFunctionCall();
|
||||
bool isVarDecl();
|
||||
bool isVirtualPropertyDecl();
|
||||
bool isFuncDecl(bool isMethod);
|
||||
bool isLambda();
|
||||
bool isFunctionCall();
|
||||
|
||||
void GetToken(sToken *token);
|
||||
void RewindTo(const sToken *token);
|
||||
void RewindErrorTo(sToken *token);
|
||||
void getToken(sToken *token);
|
||||
void rewindTo(const sToken *token);
|
||||
void rewindErrorTo(sToken *token);
|
||||
void SetPos(size_t pos);
|
||||
|
||||
bool IsRealType(int tokenType);
|
||||
bool IdentifierIs(const sToken &t, const char *str);
|
||||
bool IsDataType(const sToken &token);
|
||||
bool isRealType(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 ParseMethodAttributes();
|
||||
bool checkTemplateType(const sToken &t);
|
||||
bool parseTemplTypeList(bool required = true);
|
||||
|
||||
void ParseArgList(bool withParenthesis = true);
|
||||
void parseArgList(bool withParenthesis = true);
|
||||
|
||||
void SuperficiallyParseExpression();
|
||||
void superficiallyParseExpression();
|
||||
|
||||
private:
|
||||
bool FindTokenAfterType(sToken &nextToken);
|
||||
bool FindIdentifierAfterScope(sToken &nextToken);
|
||||
bool IsConstant(int tokenType);
|
||||
bool IsOperator(int tokenType);
|
||||
bool IsPreOperator(int tokenType);
|
||||
bool IsPostOperator(int tokenType);
|
||||
bool IsAssignOperator(int tokenType);
|
||||
bool findTokenAfterType(sToken &nextToken);
|
||||
bool findIdentifierAfterScope(sToken &nextToken);
|
||||
bool isConstant(int tokenType);
|
||||
bool isOperator(int tokenType);
|
||||
bool isPreOperator(int tokenType);
|
||||
bool isPostOperator(int tokenType);
|
||||
bool isAssignOperator(int tokenType);
|
||||
|
||||
bool DoesTypeExist(const QString &t);
|
||||
bool typeExist(const QString &t);
|
||||
|
||||
Symbol ParseFunctionDefinition();
|
||||
Symbol parseFunctionDefinition();
|
||||
|
||||
QList<Symbol> ParseDeclaration(bool isClassProp = false,
|
||||
QList<Symbol> parseDeclaration(bool isClassProp = false,
|
||||
bool isGlobalVar = false);
|
||||
|
||||
Symbol ParseInterfaceMethod();
|
||||
Symbol parseInterfaceMethod();
|
||||
|
||||
void ParseStringConstant();
|
||||
|
||||
|
@ -224,13 +235,14 @@ private:
|
|||
asCScriptEngine *engine;
|
||||
|
||||
// size_t _curscope = 0;
|
||||
SymbolTable _symtable;
|
||||
|
||||
QByteArray code;
|
||||
QByteArray tempString; // Used for reduzing amount of dynamic allocations
|
||||
|
||||
sToken lastToken;
|
||||
size_t sourcePos;
|
||||
|
||||
QByteArrayList currentNs;
|
||||
};
|
||||
|
||||
#endif // QASCODEPARSER_H
|
||||
|
|
|
@ -265,12 +265,12 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
|
||||
asBuilder builder(_engine);
|
||||
for (auto &m : PluginSystem::instance().scriptMarcos()) {
|
||||
builder.DefineWord(m);
|
||||
builder.defineWord(m);
|
||||
}
|
||||
|
||||
// Set the pragma callback so we can detect
|
||||
builder.SetPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
||||
builder.SetIncludeCallback(&ScriptMachine::includeCallback, this);
|
||||
builder.setPragmaCallback(&ScriptMachine::pragmaCallback, this);
|
||||
builder.setIncludeCallback(&ScriptMachine::includeCallback, this);
|
||||
|
||||
// Compile the script
|
||||
auto r = builder.StartNewModule("script");
|
||||
|
@ -278,7 +278,7 @@ bool ScriptMachine::executeScript(const QString &script, bool isInDebug) {
|
|||
return false;
|
||||
}
|
||||
|
||||
r = builder.AddSectionFromFile(script.toUtf8());
|
||||
r = builder.loadSectionFromFile(script.toUtf8());
|
||||
if (r < 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -522,7 +522,7 @@ int ScriptMachine::pragmaCallback(const QByteArray &pragmaText,
|
|||
const QString §ionname, void *userParam) {
|
||||
Q_UNUSED(userParam);
|
||||
|
||||
asIScriptEngine *engine = builder->GetEngine();
|
||||
asIScriptEngine *engine = builder->getEngine();
|
||||
|
||||
// Filter the pragmaText so only what is of interest remains
|
||||
// With this the user can add comments and use different whitespaces
|
||||
|
@ -589,7 +589,7 @@ int ScriptMachine::includeCallback(const QString &include, bool quotedInclude,
|
|||
inc += QStringLiteral(".as");
|
||||
}
|
||||
|
||||
return builder->AddSectionFromFile(inc);
|
||||
return builder->loadSectionFromFile(inc);
|
||||
}
|
||||
|
||||
QString ScriptMachine::processTranslation(const char *content,
|
||||
|
|
|
@ -724,25 +724,40 @@ MainWindow::buildUpNumberShowDock(ads::CDockManager *dock,
|
|||
actionGroup->setExclusive(true);
|
||||
|
||||
auto le = Utilities::checkIsLittleEndian();
|
||||
m_littleEndian = new QAction(actionGroup);
|
||||
m_littleEndian->setText(tr("LittleEndian"));
|
||||
m_littleEndian->setCheckable(true);
|
||||
m_littleEndian->setChecked(le);
|
||||
connect(m_littleEndian, &QAction::triggered, this, [=] {
|
||||
auto aLittleEndian = new QAction(actionGroup);
|
||||
aLittleEndian->setText(tr("LittleEndian"));
|
||||
aLittleEndian->setCheckable(true);
|
||||
aLittleEndian->setChecked(le);
|
||||
connect(aLittleEndian, &QAction::triggered, this, [=] {
|
||||
m_islittle = true;
|
||||
this->on_locChanged();
|
||||
});
|
||||
m_numshowtable->addAction(m_littleEndian);
|
||||
m_numshowtable->addAction(aLittleEndian);
|
||||
|
||||
m_bigEndian = new QAction(actionGroup);
|
||||
m_bigEndian->setText(tr("BigEndian"));
|
||||
m_bigEndian->setCheckable(true);
|
||||
m_bigEndian->setChecked(!le);
|
||||
connect(m_bigEndian, &QAction::triggered, this, [=] {
|
||||
auto aBigEndian = new QAction(actionGroup);
|
||||
aBigEndian->setText(tr("BigEndian"));
|
||||
aBigEndian->setCheckable(true);
|
||||
aBigEndian->setChecked(!le);
|
||||
connect(aBigEndian, &QAction::triggered, this, [=] {
|
||||
m_islittle = false;
|
||||
this->on_locChanged();
|
||||
});
|
||||
m_numshowtable->addAction(m_bigEndian);
|
||||
m_numshowtable->addAction(aBigEndian);
|
||||
|
||||
a = new QAction(this);
|
||||
a->setSeparator(true);
|
||||
m_numshowtable->addAction(a);
|
||||
|
||||
auto aUnsignedHex = new QAction(this);
|
||||
aUnsignedHex->setText(tr("UnsignedHex"));
|
||||
aUnsignedHex->setCheckable(true);
|
||||
aUnsignedHex->setChecked(false);
|
||||
connect(aUnsignedHex, &QAction::toggled, this, [=](bool b) {
|
||||
m_unsignedHex = b;
|
||||
this->on_locChanged();
|
||||
});
|
||||
m_numshowtable->addAction(aUnsignedHex);
|
||||
|
||||
m_numshowtable->setContextMenuPolicy(
|
||||
Qt::ContextMenuPolicy::ActionsContextMenu);
|
||||
|
||||
|
@ -2834,7 +2849,9 @@ void MainWindow::on_locChanged() {
|
|||
auto s = processEndian(n);
|
||||
_numsitem->setNumData(
|
||||
NumShowModel::NumTableIndex::Uint64,
|
||||
QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper()));
|
||||
m_unsignedHex
|
||||
? QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper())
|
||||
: QString::number(s));
|
||||
auto s1 = processEndian(qsizetype(n));
|
||||
_numsitem->setNumData(NumShowModel::NumTableIndex::Int64,
|
||||
QString::number(s1));
|
||||
|
@ -2853,7 +2870,9 @@ void MainWindow::on_locChanged() {
|
|||
auto s = processEndian(quint32(n));
|
||||
_numsitem->setNumData(
|
||||
NumShowModel::NumTableIndex::Uint32,
|
||||
QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper()));
|
||||
m_unsignedHex
|
||||
? QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper())
|
||||
: QString::number(s));
|
||||
auto s1 = processEndian(qint32(n));
|
||||
_numsitem->setNumData(NumShowModel::NumTableIndex::Int32,
|
||||
QString::number(s1));
|
||||
|
@ -2872,7 +2891,9 @@ void MainWindow::on_locChanged() {
|
|||
auto s = processEndian(quint16(n));
|
||||
_numsitem->setNumData(
|
||||
NumShowModel::NumTableIndex::Ushort,
|
||||
QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper()));
|
||||
m_unsignedHex
|
||||
? QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper())
|
||||
: QString::number(s));
|
||||
auto s1 = processEndian(qint16(n));
|
||||
_numsitem->setNumData(NumShowModel::NumTableIndex::Short,
|
||||
QString::number(s1));
|
||||
|
@ -2885,7 +2906,9 @@ void MainWindow::on_locChanged() {
|
|||
auto s = uchar(s1);
|
||||
_numsitem->setNumData(
|
||||
NumShowModel::NumTableIndex::Byte,
|
||||
QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper()));
|
||||
m_unsignedHex
|
||||
? QStringLiteral("0x%1").arg(QString::number(s, 16).toUpper())
|
||||
: QString::number(s));
|
||||
_numsitem->setNumData(NumShowModel::NumTableIndex::Char,
|
||||
QString::number(s1));
|
||||
} else {
|
||||
|
|
|
@ -555,9 +555,6 @@ private:
|
|||
QLabel *m_lblsellen = nullptr;
|
||||
QStatusBar *m_status = nullptr;
|
||||
|
||||
QAction *m_littleEndian = nullptr;
|
||||
QAction *m_bigEndian = nullptr;
|
||||
|
||||
QAction *m_aShowMetafg = nullptr;
|
||||
QAction *m_aShowMetabg = nullptr;
|
||||
QAction *m_aShowMetaComment = nullptr;
|
||||
|
@ -603,9 +600,6 @@ private:
|
|||
|
||||
QString m_lastusedpath;
|
||||
bool m_islittle = true;
|
||||
bool m_enablePlugin = true;
|
||||
|
||||
// Guard against recursion
|
||||
bool _isHandlingEvent = false;
|
||||
bool m_unsignedHex = false;
|
||||
};
|
||||
#endif // MAINWINDOW_H
|
||||
|
|
Loading…
Reference in New Issue