diff --git a/3rdparty/WingCodeEdit b/3rdparty/WingCodeEdit
index 4307a25..e5cef2d 160000
--- a/3rdparty/WingCodeEdit
+++ b/3rdparty/WingCodeEdit
@@ -1 +1 @@
-Subproject commit 4307a2552e52d9f7e5c8fc2bd1d3148748e968f9
+Subproject commit e5cef2dcf126037ffdc57a5aaf6a3b1d3f4c70ae
diff --git a/lang/zh_CN/winghex_zh_CN.ts b/lang/zh_CN/winghex_zh_CN.ts
index 26f316b..5e9678c 100644
--- a/lang/zh_CN/winghex_zh_CN.ts
+++ b/lang/zh_CN/winghex_zh_CN.ts
@@ -1692,7 +1692,7 @@
【错误】
-
+
ConfirmAPPSave
你尝试关闭程序,但仍存在未保存的文件或工作区,你确定保存这些更改吗?
@@ -2272,125 +2272,125 @@
总计发现设备拓展插件数目:
-
+
RegisterScriptFnUnSupportedTypes:
因脚本函数含有未支持的类型而注册失败:
-
-
+
+
RegisterScriptFnInvalidSig:
因脚本函数签名非法而注册失败:
-
-
+
+
RegisterScriptFnConflitSig:
因脚本函数签名冲突而注册失败:
-
+
InvalidEnumName:
非法枚举名:
-
+
InvalidEnumValue:
非法枚举值:
-
+
InvalidMarcosRegister:
非法宏注册:
-
+
ErrLoadPluginSDKVersion
插件加载失败:非法插件 SDK 版本!
-
+
ErrLoadPluginNoName
插件加载失败:非法插件名称!
-
+
ErrLoadInitPlugin
插件加载失败:初始化插件失败!
-
+
PluginName :
插件名:
-
+
PluginAuthor :
插件作者:
-
+
PluginWidgetRegister
注册插件对象中……
-
+
ErrLoadExtPluginSDKVersion
设备拓展插件加载失败:非法插件 SDK 版本!
-
+
ExtPluginAuthor :
设备拓展插件作者:
-
+
ExtPluginWidgetRegister
设备拓展注册插件对象中……
-
+
ErrLoadInitExtPlugin
设备拓展插件加载失败:初始化插件失败!
-
+
ChooseFile
选择文件
-
-
+
+
Error
错误
-
+
FileNotExist
文件不存在!
-
+
FilePermission
因文件权限无法继续!
-
+
EmptyNameDockWidget:
空的贴边组件名:
-
+
InvalidNameDockWidget:
无效贴边组件名:
-
+
InvalidNullDockWidget:
无效空贴边组件:
-
+
Not allowed operation in non-UI thread
该操作在非 UI 线程非法
@@ -2754,14 +2754,14 @@
-
-
+
+
Script failed to build
脚本编译失败
-
+
Cannot find 'int main()' or 'void main()'
无法找到程序入口点: "int main()" 或者 "void main()"
@@ -2777,19 +2777,19 @@
-
+
The script failed with an exception
异常被抛出,脚本执行失败
-
+
The script was aborted
脚本被终止
-
+
The script terminated unexpectedly
脚本异常退出
diff --git a/lang/zh_TW/winghex_zh_TW.ts b/lang/zh_TW/winghex_zh_TW.ts
index a70b244..e443ec8 100644
--- a/lang/zh_TW/winghex_zh_TW.ts
+++ b/lang/zh_TW/winghex_zh_TW.ts
@@ -1692,7 +1692,7 @@
【錯誤】
-
+
ConfirmAPPSave
你嘗試關閉程式,但仍存在未保存的檔或工作區,你確定保存這些更改嗎?
@@ -2272,125 +2272,125 @@
總計發現設備拓展插件數目:
-
+
RegisterScriptFnUnSupportedTypes:
因腳本函數含有未支持的類型而註冊失敗:
-
-
+
+
RegisterScriptFnInvalidSig:
因腳本函數簽名非法而註冊失敗:
-
-
+
+
RegisterScriptFnConflitSig:
因腳本函數簽名衝突而註冊失敗:
-
+
InvalidEnumName:
非法枚舉名:
-
+
InvalidEnumValue:
非法枚舉值:
-
+
InvalidMarcosRegister:
非法宏註冊:
-
+
ErrLoadPluginSDKVersion
插件加載失敗:非法插件 SDK 版本!
-
+
ErrLoadPluginNoName
插件加載失敗:非法插件名稱!
-
+
ErrLoadInitPlugin
插件加載失敗:初始化插件失敗!
-
+
PluginName :
插件名:
-
+
PluginAuthor :
插件作者:
-
+
PluginWidgetRegister
註冊插件對象中……
-
+
ErrLoadExtPluginSDKVersion
設備拓展插件加載失敗:非法插件 SDK 版本!
-
+
ExtPluginAuthor :
設備拓展插件作者:
-
+
ExtPluginWidgetRegister
設備拓展註冊插件對象中……
-
+
ErrLoadInitExtPlugin
設備拓展插件加載失敗:初始化插件失敗!
-
+
ChooseFile
選擇檔
-
-
+
+
Error
錯誤
-
+
FileNotExist
檔不存在!
-
+
FilePermission
因檔許可權無法繼續!
-
+
EmptyNameDockWidget:
空的貼邊組件名:
-
+
InvalidNameDockWidget:
無效貼邊組件名:
-
+
InvalidNullDockWidget:
無效空貼邊組件:
-
+
Not allowed operation in non-UI thread
該操作在非 UI 線程非法
@@ -2754,14 +2754,14 @@
-
-
+
+
Script failed to build
腳本編譯失敗
-
+
Cannot find 'int main()' or 'void main()'
無法找到程式入口點: "int main()" 或者 "void main()"
@@ -2777,19 +2777,19 @@
-
+
The script failed with an exception
異常被拋出,腳本執行失敗
-
+
The script was aborted
腳本被終止
-
+
The script terminated unexpectedly
腳本異常退出
diff --git a/src/class/ascompletion.cpp b/src/class/ascompletion.cpp
index 5b0455f..0eee59b 100644
--- a/src/class/ascompletion.cpp
+++ b/src/class/ascompletion.cpp
@@ -139,15 +139,15 @@ QString AsCompletion::wordSeperators() const {
return eow;
}
-void AsCompletion::processTrigger(const QString &trigger,
+bool AsCompletion::processTrigger(const QString &trigger,
const QString &content) {
if (content.isEmpty()) {
- return;
+ return false;
}
if (trigger == *SEMI_COLON_TRIGGER) {
clearFunctionTip();
- return;
+ return false;
}
auto len = content.length();
@@ -173,13 +173,14 @@ void AsCompletion::processTrigger(const QString &trigger,
QByteArray content;
};
+ auto engine = ScriptMachine::instance().engine();
+
// parse the tokens
QVector tokens;
qsizetype pos = 0;
for (; p < end;) {
asUINT tokenLen = 0;
- auto tt =
- ScriptMachine::instance().engine()->ParseToken(p, len, &tokenLen);
+ auto tt = engine->ParseToken(p, len, &tokenLen);
if (tt == asTC_WHITESPACE) {
p += tokenLen;
pos += tokenLen;
@@ -222,11 +223,16 @@ void AsCompletion::processTrigger(const QString &trigger,
QByteArray fn;
if (tokens.isEmpty()) {
popup()->hide();
- return;
+ return false;
}
QString prefix;
auto etoken = tokens.back();
+ if (etoken.type == asTC_VALUE || etoken.type == asTC_COMMENT ||
+ etoken.type == asTC_UNKNOWN) {
+ popup()->hide();
+ return false;
+ }
// if trigger is empty, it's making editing
if (trigger.isEmpty()) {
@@ -246,20 +252,21 @@ void AsCompletion::processTrigger(const QString &trigger,
if (etoken.content == *DBL_COLON_TRIGGER) {
processTrigger(*DBL_COLON_TRIGGER, content.left(etoken.pos));
setCompletionPrefix(prefix);
- return;
+ return true;
} else if (etoken.content == *DOT_TRIGGER) {
processTrigger(*DOT_TRIGGER, content.left(etoken.pos));
setCompletionPrefix(prefix);
- return;
+ return true;
} else {
applyEmptyNsNode(nodes, docNodes);
}
} else if (etoken.type != asTC_IDENTIFIER) {
popup()->hide();
- return;
+ return false;
}
if (trigger == *DOT_TRIGGER) {
+ // member guessing ?
applyClassNodes(nodes);
} else if (etoken.content.length() >= triggerAmount()) {
// completion for a.b.c or a::b.c or a::b::c.d or ::a::b.c
@@ -269,7 +276,7 @@ void AsCompletion::processTrigger(const QString &trigger,
if (idx >= 0) {
if (tokens.at(idx).content == *DOT_TRIGGER) {
popup()->hide();
- return;
+ return false;
}
}
nodes = parser.headerNodes().value(ns) +
@@ -281,7 +288,7 @@ void AsCompletion::processTrigger(const QString &trigger,
}
if (nodes.isEmpty()) {
- return;
+ return true;
}
} else if (trigger == *LEFT_PARE_TRIGGER) {
// the first is function name, an identifier
@@ -297,7 +304,7 @@ void AsCompletion::processTrigger(const QString &trigger,
if (idx >= 0 && idx < tokens.length()) {
if (tokens.at(idx).content == *DOT_TRIGGER) {
popup()->hide();
- return;
+ return false;
}
}
@@ -312,6 +319,7 @@ void AsCompletion::processTrigger(const QString &trigger,
setModel(new CodeCompletionModel(nodes, this));
setCompletionPrefix(prefix);
+ return true;
}
QList AsCompletion::parseDocument() {
@@ -387,7 +395,14 @@ QList AsCompletion::parseDocument() {
tip.type = CodeInfoTip::Type::Variable;
break;
case QAsCodeParser::SymbolType::Class:
+ case QAsCodeParser::SymbolType::Interface:
+ tip.type = CodeInfoTip::Type::Class;
+ for (auto &mem : sym.children) {
+ // TODO
+ }
+ break;
case QAsCodeParser::SymbolType::Invalid:
+ case QAsCodeParser::SymbolType::Import:
continue;
}
diff --git a/src/class/ascompletion.h b/src/class/ascompletion.h
index 525e01a..a79c8c6 100644
--- a/src/class/ascompletion.h
+++ b/src/class/ascompletion.h
@@ -38,7 +38,7 @@ public:
void clearFunctionTip();
protected:
- virtual void processTrigger(const QString &trigger,
+ virtual bool processTrigger(const QString &trigger,
const QString &content) override;
virtual QList parseDocument();
diff --git a/src/class/pluginsystem.cpp b/src/class/pluginsystem.cpp
index f5a8e63..311a48d 100644
--- a/src/class/pluginsystem.cpp
+++ b/src/class/pluginsystem.cpp
@@ -2840,6 +2840,10 @@ void PluginSystem::checkDirRootSafe(const QDir &dir) {
}
void PluginSystem::registerFns(IWingPlugin *plg) {
+ if (_angelplg == nullptr) {
+ return;
+ }
+
Q_ASSERT(plg);
auto fns = plg->registeredScriptFns();
if (fns.isEmpty()) {
@@ -2912,6 +2916,10 @@ void PluginSystem::registerFns(IWingPlugin *plg) {
}
void PluginSystem::registerUnSafeFns(IWingPlugin *plg) {
+ if (_angelplg == nullptr) {
+ return;
+ }
+
Q_ASSERT(plg);
auto fns = plg->registeredScriptUnsafeFns();
diff --git a/src/class/qascodeparser.cpp b/src/class/qascodeparser.cpp
index d46bb99..76bb720 100644
--- a/src/class/qascodeparser.cpp
+++ b/src/class/qascodeparser.cpp
@@ -81,7 +81,6 @@ QAsCodeParser::parseIntell(qsizetype offset,
case SymbolType::Function: {
sym.type = seg.additonalInfos.at(0);
sym.additonalInfo = seg.additonalInfos.at(1);
- sym.name = seg.name;
if (offset > seg.offset && offset < seg.end()) {
sym.children = parseStatementBlock(sym.scope, seg.codes,
offset - seg.offset);
@@ -121,7 +120,13 @@ QAsCodeParser::parseIntell(qsizetype offset,
}
break;
case SymbolType::Class:
+ sym.children = parseClassContent(offset, sym.scope, seg.codes);
+ break;
+ case SymbolType::Interface:
+ sym.children = parseInterfaceContent(offset, sym.scope, seg.codes);
+ break;
case SymbolType::Invalid:
+ case SymbolType::Import:
continue;
}
@@ -440,6 +445,49 @@ QByteArray QAsCodeParser::parseType(bool allowConst, bool allowVariableType,
return dtType;
}
+QAsCodeParser::Symbol
+QAsCodeParser::parseFuncDefContent(const QByteArrayList &ns) {
+ Symbol sym;
+
+ sToken t1;
+ getToken(&t1);
+
+ if (t1.type != ttFuncDef) {
+ rewindErrorTo(&t1);
+ return sym;
+ }
+
+ sym.type = parseType(true);
+ if (_isSyntaxError)
+ return sym;
+
+ parseTypeMod(false);
+ if (_isSyntaxError)
+ return sym;
+
+ auto iden = parseIdentifier();
+ if (_isSyntaxError)
+ return sym;
+
+ sym.scope = ns;
+ sym.name = getSymbolString(iden);
+ sym.offset = iden.pos;
+
+ auto args = parseParameterListContent();
+ if (_isSyntaxError)
+ return sym;
+ sym.children = args;
+
+ getToken(&t1);
+ if (t1.type != ttEndStatement) {
+ rewindErrorTo(&t1);
+ return sym;
+ }
+
+ sym.symtype = SymbolType::FnDef;
+ return sym;
+}
+
QList
QAsCodeParser::parseStatementBlock(const QByteArrayList &ns,
const QByteArray &code, qsizetype end) {
@@ -744,10 +792,7 @@ sToken QAsCodeParser::superficiallyParseStatementBlock() {
level--;
else if (t1.type == ttStartStatementBlock)
level++;
- else if (t1.type == ttNonTerminatedStringConstant) {
- rewindErrorTo(&t1);
- return t1;
- } else if (t1.type == ttEnd) {
+ else if (t1.type == ttEnd) {
rewindErrorTo(&start);
return start;
}
@@ -928,12 +973,13 @@ QAsCodeParser::CodeSegment QAsCodeParser::parseInterface() {
auto id = parseIdentifier();
seg.name = getSymbolString(id);
- seg.offset = id.pos;
+
seg.scope = currentNs;
- seg.type = SymbolType::Class;
+ seg.type = SymbolType::Interface;
// External shared declarations are ended with ';'
getToken(&t);
+ seg.offset = t.pos;
if (t.type == ttEndStatement) {
rewindTo(&t);
parseToken(ttEndStatement);
@@ -1005,17 +1051,6 @@ void QAsCodeParser::superficiallyParseVarInit() {
}
}
-void QAsCodeParser::parseStatement() {
- sToken t1;
-
- getToken(&t1);
- rewindTo(&t1);
-
- // TODO
- if (isVarDecl()) {
- }
-}
-
QList
QAsCodeParser::parseDeclaration(const QByteArrayList &ns, bool isClassProp,
bool isGlobalVar) {
@@ -1107,10 +1142,14 @@ QList QAsCodeParser::parseScript(bool inBlock) {
rewindTo(&tStart);
if (t1.type == ttImport) {
+ CodeSegment seg;
+ seg.offset = t1.pos;
+
+ seg.type = SymbolType::Import;
+ segs << seg;
+
// import we don't support just skip
skipCodeBlock();
- // add empty invalid segment
- segs << CodeSegment();
} else if (t1.type == ttEnum) // Handle enumerations
segs << parseEnumeration();
else if (t1.type == ttTypedef) // Handle primitive typedefs
@@ -1235,12 +1274,13 @@ QAsCodeParser::CodeSegment QAsCodeParser::parseClass() {
auto cls = parseIdentifier();
seg.name = getSymbolString(cls);
- seg.offset = cls.pos;
+
seg.scope = currentNs;
seg.type = SymbolType::Class;
// External shared declarations are ended with ';'
getToken(&t);
+ seg.offset = t.pos;
if (t.type == ttEndStatement) {
rewindTo(&t);
parseToken(ttEndStatement);
@@ -1383,112 +1423,103 @@ QAsCodeParser::parseGlobalVarDecls(const QByteArrayList &ns,
return parseDeclaration(ns, false, true);
}
-QAsCodeParser::CodeSegment QAsCodeParser::parseFunction(bool isMethod) {
- CodeSegment fn;
+QAsCodeParser::CodeSegment QAsCodeParser::parseFunctionMethod() {
+ CodeSegment seg;
sToken t1;
getToken(&t1);
- if (!isMethod) {
- // A global function can be marked as shared and external
- while (t1.type == ttIdentifier) {
- if (identifierIs(t1, SHARED_TOKEN) ||
- identifierIs(t1, EXTERNAL_TOKEN)) {
- rewindTo(&t1);
- parseIdentifier();
- if (_isSyntaxError)
- return fn;
- } else
- break;
-
- getToken(&t1);
- }
- }
-
// A class method can start with 'private' or 'protected'
- if (isMethod && t1.type == ttPrivate) {
+ if (t1.type == ttPrivate) {
rewindTo(&t1);
parseToken(ttPrivate);
getToken(&t1);
- } else if (isMethod && t1.type == ttProtected) {
+ } else if (t1.type == ttProtected) {
rewindTo(&t1);
parseToken(ttProtected);
getToken(&t1);
}
if (_isSyntaxError)
- return fn;
+ return seg;
// If it is a global function, or a method, except constructor and
// destructor, then the return type is parsed
sToken t2;
getToken(&t2);
rewindTo(&t1);
- if (!isMethod || (t1.type != ttBitNot && t2.type != ttOpenParenthesis)) {
+ if (t1.type != ttBitNot && t2.type != ttOpenParenthesis) {
auto id = parseType(true);
if (_isSyntaxError)
- return fn;
- fn.additonalInfos.append(id);
+ return seg;
+ seg.additonalInfos.append(id);
parseTypeMod(false);
if (_isSyntaxError)
- return fn;
+ return seg;
}
// If this is a class destructor then it starts with ~, and no return type
// is declared
- if (isMethod && t1.type == ttBitNot) {
+ if (t1.type == ttBitNot) {
parseToken(ttBitNot);
if (_isSyntaxError)
- return fn;
+ return seg;
}
auto iden = parseIdentifier();
if (_isSyntaxError)
- return fn;
- fn.name = getSymbolString(iden);
- fn.offset = iden.pos;
+ return seg;
+ seg.name = getSymbolString(iden);
+ seg.offset = iden.pos;
auto params = parseParameterListContent();
if (_isSyntaxError)
- return fn;
- if (!params.isEmpty()) {
- if (fn.additonalInfos.isEmpty()) {
- fn.additonalInfos.append(QByteArray());
+ return seg;
+
+ if (seg.additonalInfos.isEmpty()) {
+ seg.additonalInfos.append(QByteArray());
+ }
+ if (params.isEmpty()) {
+ seg.additonalInfos.append(QByteArray());
+ } else {
+ QByteArrayList args;
+ for (auto &p : params) {
+ args.append(p.type + ' ' + p.name);
}
- // fn.additonalInfos;
+ seg.additonalInfos.append(args.join(", "));
}
- if (isMethod) {
- getToken(&t1);
- rewindTo(&t1);
+ getToken(&t1);
+ rewindTo(&t1);
- // Is the method a const?
- if (t1.type == ttConst)
- parseToken(ttConst);
- }
+ // Is the method a const?
+ if (t1.type == ttConst)
+ parseToken(ttConst);
// TODO: Should support abstract methods, in which case no statement block
// should be provided
parseMethodAttributes();
if (_isSyntaxError)
- return fn;
+ return seg;
// External shared functions must be ended with ';'
getToken(&t1);
rewindTo(&t1);
+
+ seg.scope = currentNs;
+
if (t1.type == ttEndStatement) {
parseToken(ttEndStatement);
- // fn.ns = _curns;
- return fn;
+ return seg;
}
- // We should just find the end of the statement block here. The statements
- // will be parsed on request by the compiler once it starts the compilation.
- superficiallyParseStatementBlock();
- // fn.ns = _curns;
- // fn.code = code.mid(t1.pos, sourcePos - t1.pos);
- // fn.valid = true;
- return fn;
+ auto begin = t1.pos;
+
+ // We should just find the end of the statement block here.
+ t1 = superficiallyParseStatementBlock();
+ auto end = t1.pos;
+ seg.codes = _code.sliced(begin, end - begin + 1);
+ return seg;
}
QAsCodeParser::Symbol
@@ -1496,50 +1527,11 @@ QAsCodeParser::parseFuncDefContent(const QByteArrayList &ns,
const QByteArray &code) {
reset();
_code = code;
-
- Symbol sym;
-
- sToken t1;
- getToken(&t1);
-
- if (t1.type != ttFuncDef) {
- rewindErrorTo(&t1);
- return sym;
- }
-
- sym.type = parseType(true);
- if (_isSyntaxError)
- return sym;
-
- parseTypeMod(false);
- if (_isSyntaxError)
- return sym;
-
- auto iden = parseIdentifier();
- if (_isSyntaxError)
- return sym;
-
- sym.scope = ns;
- sym.name = getSymbolString(iden);
- sym.offset = iden.pos;
-
- auto args = parseParameterListContent();
- if (_isSyntaxError)
- return sym;
- sym.children = args;
-
- getToken(&t1);
- if (t1.type != ttEndStatement) {
- rewindErrorTo(&t1);
- return sym;
- }
-
- sym.symtype = SymbolType::FnDef;
- return sym;
+ return parseFuncDefContent(ns);
}
QList
-QAsCodeParser::parseClassContent(const QByteArrayList &ns,
+QAsCodeParser::parseClassContent(qsizetype offset, const QByteArrayList &ns,
const QByteArray &code) {
reset();
_code = code;
@@ -1552,15 +1544,27 @@ QAsCodeParser::parseClassContent(const QByteArrayList &ns,
// Optional list of interfaces that are being implemented and classes that
// are being inherited
if (t.type == ttColon) {
- // TODO: dont support temperily, later
- parseOptionalScope();
- parseIdentifier();
+ Symbol inhertSym;
+
+ // assuming it as an interface
+ inhertSym.symtype = SymbolType::Interface;
+
+ Symbol isym;
+ isym.scope = parseOptionalScope();
+ isym.name = getSymbolString(parseIdentifier());
+ isym.symtype = SymbolType::Class; // assuming it as a class
+
+ inhertSym.children.append(isym);
+
getToken(&t);
while (t.type == ttListSeparator) {
- parseOptionalScope();
- parseIdentifier();
+ isym.scope = parseOptionalScope();
+ isym.name = getSymbolString(parseIdentifier());
+ inhertSym.children.append(isym);
getToken(&t);
}
+
+ syms.append(inhertSym);
}
if (t.type != ttStartStatementBlock) {
@@ -1574,23 +1578,32 @@ QAsCodeParser::parseClassContent(const QByteArrayList &ns,
while (t.type != ttEndStatementBlock && t.type != ttEnd) {
// Is it a property or a method?
if (t.type == ttFuncDef) {
- // auto fndef = parseFuncDefContent();
- // if (fndef.isValid()) {
- // clssym.content.append(fndef);
- // }
+ auto fndef = parseFuncDefContent(ns);
+ syms.append(fndef);
} else if (isFuncDecl(true)) {
- auto fn = parseFunction(true);
- // if (fn.isValid()) {
- // clssym.codesegs.insert(fn.nameInSrc, fn);
- // }
+ auto fn = parseFunctionMethod();
+
+ // add function symbols
+ Symbol sym;
+ sym.symtype = fn.type;
+ sym.scope = fn.scope;
+ sym.offset = fn.offset;
+ sym.name = fn.name;
+ sym.type = fn.additonalInfos.at(0);
+ sym.additonalInfo = fn.additonalInfos.at(1);
+ syms.append(sym);
+
+ // deep parsing
+ if (offset >= fn.offset && offset < fn.end()) {
+ auto ss = parseStatementBlock(fn.scope, fn.codes, offset);
+ syms.append(ss);
+ }
} else if (isVirtualPropertyDecl()) {
auto vp = parseVirtualPropertyDecl(true, false);
- // if (vp.isValid()) {
- // clssym.content.append(vp);
- // }
+ syms.append(vp);
} else if (isVarDecl()) {
- // auto decl = parseDeclaration(true);
- // clssym.content.append(decl);
+ auto decl = parseDeclaration(ns, true);
+ syms.append(decl);
} else if (t.type == ttEndStatement)
// Skip empty declarations
getToken(&t);
@@ -1615,53 +1628,14 @@ QAsCodeParser::parseClassContent(const QByteArrayList &ns,
return syms;
}
-void QAsCodeParser::parseMixinContent() {
- sToken t;
- getToken(&t);
-
- if (t.type != ttMixin) {
- rewindErrorTo(&t);
- return;
- }
-
- // A mixin token must be followed by a class declaration
- // parseClassContent();
-}
-
-void QAsCodeParser::parseInterfaceContent() {
- Symbol sym;
+QList
+QAsCodeParser::parseInterfaceContent(qsizetype offset, const QByteArrayList &ns,
+ const QByteArray &code) {
+ QList syms;
sToken t;
- // Allow keywords 'external' and 'shared' before 'interface'
getToken(&t);
- while (identifierIs(t, SHARED_TOKEN) || identifierIs(t, EXTERNAL_TOKEN)) {
- rewindTo(&t);
- parseIdentifier();
-
- if (_isSyntaxError)
- return;
-
- getToken(&t);
- }
-
- if (t.type != ttInterface) {
- rewindErrorTo(&t);
- return;
- }
-
- auto id = parseIdentifier();
- sym.name = getSymbolString(id);
- // sym.nameInSrc = id.pos;
-
- // External shared declarations are ended with ';'
- getToken(&t);
- if (t.type == ttEndStatement) {
- rewindTo(&t);
- parseToken(ttEndStatement);
- return;
- }
-
// Can optionally have a list of interfaces that are inherited
if (t.type == ttColon) {
parseOptionalScope();
@@ -1676,7 +1650,7 @@ void QAsCodeParser::parseInterfaceContent() {
if (t.type != ttStartStatementBlock) {
rewindErrorTo(&t);
- return;
+ return {};
}
// Parse interface methods
@@ -1685,22 +1659,18 @@ void QAsCodeParser::parseInterfaceContent() {
while (t.type != ttEndStatementBlock && t.type != ttEnd) {
if (isVirtualPropertyDecl()) {
auto vp = parseVirtualPropertyDecl(true, true);
- // if (vp.isValid()) {
- // sym.content.append(vp);
- // }
+ syms.append(vp);
} else if (t.type == ttEndStatement) {
// Skip empty declarations
getToken(&t);
} else {
// Parse the method signature
auto im = parseInterfaceMethod();
- // if (im.isValid()) {
- // sym.content.append(im);
- // }
+ syms.append(im);
}
if (_isSyntaxError)
- return;
+ return syms;
getToken(&t);
rewindTo(&t);
@@ -1709,8 +1679,10 @@ void QAsCodeParser::parseInterfaceContent() {
getToken(&t);
if (t.type != ttEndStatementBlock) {
rewindErrorTo(&t);
- return;
+ return syms;
}
+
+ return syms;
}
QAsCodeParser::Symbol QAsCodeParser::parseInterfaceMethod() {
@@ -1719,7 +1691,7 @@ QAsCodeParser::Symbol QAsCodeParser::parseInterfaceMethod() {
auto ret = parseType(true);
if (_isSyntaxError)
return sym;
- // sym.typeStr = getSymbolString(ret);
+ sym.type = ret;
parseTypeMod(false);
if (_isSyntaxError)
@@ -1729,12 +1701,13 @@ QAsCodeParser::Symbol QAsCodeParser::parseInterfaceMethod() {
if (_isSyntaxError)
return sym;
sym.name = getSymbolString(id);
- // sym.nameInSrc = id.pos;
+ sym.offset = id.pos;
auto args = parseParameterListContent();
if (_isSyntaxError)
return sym;
- // sym.content = args;
+
+ sym.children = args;
// Parse an optional const after the method definition
sToken t1;
@@ -1749,7 +1722,7 @@ QAsCodeParser::Symbol QAsCodeParser::parseInterfaceMethod() {
return sym;
}
- // sym.type = SymbolType::FnDecl;
+ sym.symtype = SymbolType::Function;
return sym;
}
@@ -1777,7 +1750,7 @@ QAsCodeParser::parseVirtualPropertyDecl(bool isMethod, bool isInterface) {
auto id = parseType(true);
if (_isSyntaxError)
return sym;
- // sym.typeStr = getSymbolString(id);
+ sym.type = id;
parseTypeMod(false);
if (_isSyntaxError)
@@ -1787,7 +1760,7 @@ QAsCodeParser::parseVirtualPropertyDecl(bool isMethod, bool isInterface) {
if (_isSyntaxError)
return sym;
sym.name = getSymbolString(iden);
- // sym.nameInSrc = iden.pos;
+ sym.offset = iden.pos;
getToken(&t1);
if (t1.type != ttStartStatementBlock) {
@@ -1825,11 +1798,7 @@ QAsCodeParser::parseVirtualPropertyDecl(bool isMethod, bool isInterface) {
if (t1.type == ttStartStatementBlock) {
rewindTo(&t1);
superficiallyParseStatementBlock();
-
- // seg.valid = true;
- // seg.code = code.mid(t1.pos, sourcePos - t1.pos);
- // sym.codesegs.insert(t1.pos, seg);
-
+ // TODO: support deep parsing ?
if (_isSyntaxError)
return sym;
} else if (t1.type == ttEndStatement) {
@@ -1861,7 +1830,7 @@ QAsCodeParser::parseVirtualPropertyDecl(bool isMethod, bool isInterface) {
}
}
- // sym.type = SymbolType::Property;
+ sym.symtype = SymbolType::Variable;
return sym;
}
@@ -2206,75 +2175,6 @@ bool QAsCodeParser::isFuncDecl(
return false;
}
-bool QAsCodeParser::isLambda() {
- bool isLambda = false;
- sToken t;
- getToken(&t);
- if (t.type == ttIdentifier && identifierIs(t, FUNCTION_TOKEN)) {
- sToken t2;
- getToken(&t2);
- if (t2.type == ttOpenParenthesis) {
- // Skip until )
- while (t2.type != ttCloseParenthesis && t2.type != ttEnd)
- getToken(&t2);
-
- // The next token must be a {
- getToken(&t2);
- if (t2.type == ttStartStatementBlock)
- isLambda = true;
- }
- }
-
- rewindTo(&t);
- return isLambda;
-}
-
-bool QAsCodeParser::isFunctionCall() {
- sToken s;
- sToken t1, t2;
-
- getToken(&s);
- t1 = s;
-
- // A function call may be prefixed with scope resolution
- if (t1.type == ttScope)
- getToken(&t1);
- getToken(&t2);
-
- while (t1.type == ttIdentifier && t2.type == ttScope) {
- getToken(&t1);
- getToken(&t2);
- }
-
- // A function call starts with an identifier followed by an argument list
- // The parser doesn't have enough RewindErrorTormation about scope to
- // determine if the identifier is a datatype, so even if it happens to be
- // the parser will identify the expression as a function call rather than a
- // construct call. The compiler will sort this out later
- if (t1.type != ttIdentifier) {
- rewindTo(&s);
- return false;
- }
-
- if (t2.type == ttOpenParenthesis) {
- rewindTo(&s);
- return true;
- }
-
- rewindTo(&s);
- return false;
-}
-
-void QAsCodeParser::ParseStringConstant() {
- sToken t;
- getToken(&t);
- if (t.type != ttStringConstant && t.type != ttMultilineStringConstant &&
- t.type != ttHeredocStringConstant) {
- rewindErrorTo(&t);
- return;
- }
-}
-
bool QAsCodeParser::findTokenAfterType(
sToken &nextToken) { // Set a rewind point
sToken t, t1;
@@ -2369,43 +2269,6 @@ bool QAsCodeParser::findTokenAfterType(
return true;
}
-bool QAsCodeParser::findIdentifierAfterScope(sToken &nextToken) {
- sToken t1, t2, t3;
-
- // Determine the last identifier after scope in order to check if it is a
- // type
- getToken(&t1);
- getToken(&t2);
- rewindTo(&t1);
-
- if (t1.type != ttScope && t2.type != ttScope) {
- if (t1.type == ttIdentifier) {
- nextToken = t1;
- return true;
- }
- return false;
- }
-
- if (t1.type == ttScope)
- t3 = t2;
- else
- t3 = t1;
- rewindTo(&t3);
- getToken(&t2);
- while (t3.type == ttIdentifier) {
- t2 = t3;
- getToken(&t3);
- if (t3.type == ttScope)
- getToken(&t3);
- else
- break;
- }
- rewindTo(&t1);
- nextToken = t2;
-
- return true;
-}
-
bool QAsCodeParser::isConstant(int tokenType) {
if (tokenType == ttIntConstant || tokenType == ttFloatConstant ||
tokenType == ttDoubleConstant || tokenType == ttStringConstant ||
diff --git a/src/class/qascodeparser.h b/src/class/qascodeparser.h
index b655960..bfd6742 100644
--- a/src/class/qascodeparser.h
+++ b/src/class/qascodeparser.h
@@ -24,7 +24,7 @@
#include
#include
-// This class is the modification of as_parser.
+// This class comes from as_parser.h .
// 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.
@@ -41,16 +41,17 @@ public:
public:
enum class SymbolType {
Invalid,
- Variable, // variable or property in class
- Enum, // an enum
- Class, // a class type
- Function, // a function
- TypeDef, // a typedef
- FnDef, // a funcdef
+ Variable, // variable or property in class
+ Enum, // an enum
+ Class, // a class type
+ Function, // a function
+ TypeDef, // a typedef
+ FnDef, // a funcdef
+ Interface, // an interface
+ Import, // import but not supported
};
enum class Visiblity { Public, Private, Protected };
-
/**
* @brief The CodeSegment class
*/
@@ -133,6 +134,7 @@ private:
CodeSegment parseInterface();
CodeSegment parseFuncDef();
CodeSegment parseFunction();
+ CodeSegment parseFunctionMethod();
private:
// parse tokens
@@ -168,18 +170,19 @@ private:
Symbol parseFuncDefContent(const QByteArrayList &ns,
const QByteArray &code);
- QList parseClassContent(const QByteArrayList &ns,
+ Symbol parseFuncDefContent(const QByteArrayList &ns);
+
+ QList parseClassContent(qsizetype offset, const QByteArrayList &ns,
const QByteArray &code);
+ QList parseInterfaceContent(qsizetype offset,
+ const QByteArrayList &ns,
+ const QByteArray &code);
+
QList parseStatementBlock(const QByteArrayList &ns,
const QByteArray &code, qsizetype end);
private:
- void parseStatement();
- void parseMixinContent();
- void parseInterfaceContent();
- CodeSegment parseFunction(bool isMethod);
-
Symbol parseVirtualPropertyDecl(bool isMethod, bool isInterface);
QList parseParameterListContent();
@@ -192,8 +195,6 @@ private:
bool isVarDecl();
bool isVirtualPropertyDecl();
bool isFuncDecl(bool isMethod);
- bool isLambda();
- bool isFunctionCall();
void getToken(sToken *token);
void rewindTo(const sToken *token);
@@ -209,14 +210,11 @@ private:
private:
bool findTokenAfterType(sToken &nextToken);
- bool findIdentifierAfterScope(sToken &nextToken);
bool typeExist(const QString &t);
Symbol parseInterfaceMethod();
- void ParseStringConstant();
-
private:
bool _errorWhileParsing;
bool _isSyntaxError;
diff --git a/src/class/scriptmachine.cpp b/src/class/scriptmachine.cpp
index 27ef928..15e3e38 100644
--- a/src/class/scriptmachine.cpp
+++ b/src/class/scriptmachine.cpp
@@ -1825,7 +1825,10 @@ bool ScriptMachine::executeCode(ConsoleMode mode, const QString &code) {
auto ret = parser.parse(ccode);
// check whether there is any enum/class
- if (ret.isEmpty()) {
+ if (std::find_if(ret.begin(), ret.end(),
+ [](const QAsCodeParser::CodeSegment &seg) {
+ return seg.isValid();
+ }) == ret.end()) {
// ok, wrap the codes
ccode.prepend("void main(){").append("}");
// start to compile
diff --git a/src/dialog/mainwindow.cpp b/src/dialog/mainwindow.cpp
index 136334d..08df9d5 100644
--- a/src/dialog/mainwindow.cpp
+++ b/src/dialog/mainwindow.cpp
@@ -3786,13 +3786,15 @@ void MainWindow::closeEvent(QCloseEvent *event) {
}
// then checking the scripting dialog
- if (!m_scriptDialog->about2Close()) {
- event->ignore();
- return;
- }
+ if (m_scriptDialog) {
+ if (!m_scriptDialog->about2Close()) {
+ event->ignore();
+ return;
+ }
- // then abort all script running
- ScriptMachine::instance().abortScript();
+ // then abort all script running
+ ScriptMachine::instance().abortScript();
+ }
// then checking itself
if (!m_views.isEmpty()) {
@@ -3843,9 +3845,11 @@ void MainWindow::closeEvent(QCloseEvent *event) {
auto &set = SettingManager::instance();
set.setDockLayout(m_dock->saveState());
- m_scriptDialog->saveDockLayout();
- set.setRecentFiles(m_recentmanager->saveRecent());
- set.save();
+ if (m_scriptDialog) {
+ m_scriptDialog->saveDockLayout();
+ set.setRecentFiles(m_recentmanager->saveRecent());
+ set.save();
+ }
PluginSystem::instance().destory();