Some improvements in the Script autocompletion
parent
f865481b03
commit
828231c625
|
|
@ -427,28 +427,40 @@ void CodeCompletion::update()
|
|||
QString id = blockText;
|
||||
id.remove(QRegExp(".* ")).remove(QRegExp("\\.[a-zA-Z0-9]*"));
|
||||
QString type = getIdTypes().value(id);
|
||||
int blockPosition = getBlockPosition(id);
|
||||
BlockInfo blockInfo = getBlockInfo(blockPosition);
|
||||
|
||||
qDebug() << "dot expression:" << id << type;
|
||||
// Classes
|
||||
qDebug() << "lvalue info:" << blockInfo.properties.keys() << blockInfo.properties.value("actionName") << blockInfo.properties.value("actionTypeId");
|
||||
|
||||
// Append properties of the type
|
||||
foreach (const QString &property, m_classes.value(type).properties) {
|
||||
entries.append(CompletionModel::Entry(property, property, "property"));
|
||||
}
|
||||
// Append user-defined properties of the type
|
||||
foreach (const QString &property, blockInfo.properties.keys()) {
|
||||
CompletionModel::Entry entry(property, property, "property");
|
||||
if (!entries.contains(entry)) {
|
||||
entries.append(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Append methods of the item
|
||||
foreach (const QString &method, m_classes.value(type).methods) {
|
||||
QString paramString;
|
||||
// If it's an execute() call, also autocomplete the params
|
||||
if (method == "execute") {
|
||||
int blockposition = getBlockPosition(id);
|
||||
qDebug() << "Blockposition:" << blockposition;
|
||||
if (blockposition >= 0) {
|
||||
BlockInfo info = getBlockInfo(blockposition);
|
||||
qDebug() << "actionType" << info.properties.keys() << info.properties.value("actionName") << info.properties.value("actionTypeId");
|
||||
if (info.valid) {
|
||||
QString thingId = info.properties.value("thingId");
|
||||
qDebug() << "Blockposition:" << blockPosition;
|
||||
if (blockPosition >= 0) {
|
||||
if (blockInfo.valid) {
|
||||
QString thingId = blockInfo.properties.value("thingId");
|
||||
Device *d = m_engine->thingManager()->things()->getDevice(QUuid(thingId));
|
||||
if (d) {
|
||||
ActionType *at = nullptr;
|
||||
if (info.properties.contains("actionTypeId")) {
|
||||
at = d->thingClass()->actionTypes()->getActionType(info.properties.value("actionTypeId"));
|
||||
} else if (info.properties.contains("actionName")) {
|
||||
at = d->thingClass()->actionTypes()->findByName(info.properties.value("actionName"));
|
||||
if (blockInfo.properties.contains("actionTypeId")) {
|
||||
at = d->thingClass()->actionTypes()->getActionType(blockInfo.properties.value("actionTypeId"));
|
||||
} else if (blockInfo.properties.contains("actionName")) {
|
||||
at = d->thingClass()->actionTypes()->findByName(blockInfo.properties.value("actionName"));
|
||||
}
|
||||
if (at) {
|
||||
QStringList params;
|
||||
|
|
@ -466,6 +478,10 @@ void CodeCompletion::update()
|
|||
}
|
||||
entries.append(CompletionModel::Entry(method + "(", method, "method", "", paramString + ")"));
|
||||
}
|
||||
// User-defined functions of the item
|
||||
foreach (const QString &function, blockInfo.functions) {
|
||||
entries.append(CompletionModel::Entry(function + "(", function, "method", "", ")"));
|
||||
}
|
||||
// Attached classes/properties
|
||||
foreach (const QString &property, m_attachedClasses.value(id).properties) {
|
||||
entries.append(CompletionModel::Entry(property, property, "property"));
|
||||
|
|
@ -595,8 +611,9 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const
|
|||
}
|
||||
|
||||
info.start = blockStart.position();
|
||||
info.end = blockEnd.position(); //m_document->textDocument()->find("}", position).position();
|
||||
info.end = blockEnd.position();
|
||||
info.valid = true;
|
||||
// qDebug() << "Block start:" << info.start << "end:" << info.end;
|
||||
|
||||
info.name = blockStart.block().text();
|
||||
info.name.remove(QRegExp(" *\\{ *"));
|
||||
|
|
@ -607,14 +624,11 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const
|
|||
int childBlocks = 0;
|
||||
while (!blockStart.isNull() && blockStart.position() < info.end) {
|
||||
QString line = blockStart.block().text();
|
||||
if (line.endsWith("{")) {
|
||||
// qDebug() << "line:" << line;
|
||||
if (line.contains("{") && !line.contains("}")) {
|
||||
childBlocks++;
|
||||
if (!blockStart.movePosition(QTextCursor::NextBlock)) {
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (line.trimmed().startsWith("}")) {
|
||||
if (line.contains("}") && !line.contains("{")) {
|
||||
childBlocks--;
|
||||
if (!blockStart.movePosition(QTextCursor::NextBlock)) {
|
||||
break;
|
||||
|
|
@ -622,18 +636,30 @@ CodeCompletion::BlockInfo CodeCompletion::getBlockInfo(int position) const
|
|||
continue;
|
||||
}
|
||||
// \n
|
||||
if (childBlocks > 1) { // Skip all stuff in child blocks
|
||||
if (childBlocks > 1 && !(childBlocks == 2 && line.trimmed().startsWith("function"))) { // Skip all stuff in child blocks
|
||||
// qDebug() << "skipping line in child block" << childBlocks;
|
||||
blockStart.movePosition(QTextCursor::NextBlock);
|
||||
continue;
|
||||
}
|
||||
foreach (const QString &statement, blockStart.block().text().split(";")) {
|
||||
// qDebug() << "analysing statement:" << statement;
|
||||
QStringList parts = statement.split(":");
|
||||
if (parts.length() != 2) {
|
||||
continue;
|
||||
if (parts.length() == 2) { // Properties must be "foo: bar"
|
||||
QString propName = parts.first().trimmed();
|
||||
if (propName.split(" ").count() > 1) { // trim modifiers e.g. "property bool foo: bar"
|
||||
propName = propName.split(" ").last();
|
||||
}
|
||||
if (propName.contains(".")) { // skip attached properties e.g. "Component.onCompleted: ..."
|
||||
continue;
|
||||
}
|
||||
QString propValue = parts.last().split("//").first().trimmed().remove("\"");
|
||||
info.properties.insert(propName, propValue);
|
||||
}
|
||||
parts = statement.trimmed().split(" ");
|
||||
if (parts.count() >= 2 && parts.first().trimmed() == "function") {
|
||||
QString functionHeader = parts.at(1).trimmed();
|
||||
info.functions.append(functionHeader.split("(").first());
|
||||
}
|
||||
QString propName = parts.first().trimmed();
|
||||
QString propValue = parts.last().split("//").first().trimmed().remove("\"");
|
||||
info.properties.insert(propName, propValue);
|
||||
}
|
||||
if (!blockStart.movePosition(QTextCursor::NextBlock)) {
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ private:
|
|||
bool valid = false;
|
||||
QString name;
|
||||
QHash<QString, QString> properties;
|
||||
QStringList functions;
|
||||
int start = -1;
|
||||
int end = -1;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -81,6 +81,7 @@ CompletionModel::Entry CompletionModel::get(int index)
|
|||
return m_list.at(index);
|
||||
}
|
||||
|
||||
|
||||
//************************************************
|
||||
// CompletionProxyModel
|
||||
//************************************************
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ public:
|
|||
QString decoration;
|
||||
QString decorationProperty;
|
||||
QString trailingText;
|
||||
bool operator==(const Entry &other) const {
|
||||
return text == other.text && displayText == other.displayText;
|
||||
}
|
||||
};
|
||||
|
||||
CompletionModel(QObject *parent = nullptr);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include <QMetaObject>
|
||||
#include <QTextDocumentFragment>
|
||||
#include <QQuickItem>
|
||||
#include <QRegularExpression>
|
||||
|
||||
class ScriptSyntaxHighlighterPrivate: public QSyntaxHighlighter
|
||||
{
|
||||
|
|
@ -62,7 +63,7 @@ private:
|
|||
};
|
||||
struct HighlightingRule
|
||||
{
|
||||
QRegExp pattern;
|
||||
QRegularExpression pattern;
|
||||
QTextCharFormat format;
|
||||
};
|
||||
QVector<HighlightingRule> highlightingRules;
|
||||
|
|
@ -118,19 +119,19 @@ void ScriptSyntaxHighlighterPrivate::update(bool dark)
|
|||
|
||||
// ClassNames
|
||||
format.setForeground(dark ? QColor("#55fc49") : QColor("#800080"));
|
||||
rule.pattern = QRegExp("\\b[A-Z][a-zA-Z0-9_]+\\b");
|
||||
rule.pattern = QRegularExpression("\\b[A-Z][a-zA-Z0-9_]+\\b");
|
||||
rule.format = format;
|
||||
highlightingRules.append(rule);
|
||||
|
||||
// Property bindings
|
||||
format.setForeground(dark ? QColor("#ff5555") : QColor("#800000"));
|
||||
rule.pattern = QRegExp("[a-zA-Z][a-zA-Z0-9_.]+:");
|
||||
rule.pattern = QRegularExpression("[a-zA-Z][a-zA-Z0-9_.]+:");
|
||||
rule.format = format;
|
||||
highlightingRules.append(rule);
|
||||
|
||||
// imports
|
||||
format.clearForeground();
|
||||
rule.pattern = QRegExp("import .*$");
|
||||
rule.pattern = QRegularExpression("import .*$");
|
||||
rule.format = format;
|
||||
highlightingRules.append(rule);
|
||||
|
||||
|
|
@ -158,13 +159,14 @@ void ScriptSyntaxHighlighterPrivate::update(bool dark)
|
|||
"\\bbool\\b",
|
||||
"\\bint\\b",
|
||||
"\\breal\\b",
|
||||
"\\bdouble\\b",
|
||||
"\\bdate\\b",
|
||||
"\\btrue\\b",
|
||||
"\\bfalse\\b",
|
||||
};
|
||||
format.setForeground(dark ? Qt::yellow : QColor("#80831a"));
|
||||
foreach (const QString &pattern, keywordPatterns) {
|
||||
rule.pattern = QRegExp(pattern);
|
||||
rule.pattern = QRegularExpression(pattern);
|
||||
rule.format = format;
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
|
@ -172,17 +174,15 @@ void ScriptSyntaxHighlighterPrivate::update(bool dark)
|
|||
// String literals
|
||||
format.setForeground(dark ? QColor("#e64ad7") : Qt::darkGreen);
|
||||
rule.format = format;
|
||||
rule.pattern = QRegExp("\".[^\"]*\"");
|
||||
highlightingRules.append(rule);
|
||||
rule.pattern = QRegExp("'.[^']*'");
|
||||
rule.pattern = QRegularExpression(R"**((?<!\\)([\"'])(.*?)(?<!\\)\1)**", QRegularExpression::DotMatchesEverythingOption | QRegularExpression::MultilineOption);
|
||||
highlightingRules.append(rule);
|
||||
|
||||
// comments
|
||||
format.setForeground(dark ? Qt::cyan : Qt::darkGray);
|
||||
rule.format = format;
|
||||
rule.pattern = QRegExp("//.*$");
|
||||
rule.pattern = QRegularExpression("//.*$");
|
||||
highlightingRules.append(rule);
|
||||
rule.pattern = QRegExp("/*.*\\*/");
|
||||
rule.pattern = QRegularExpression("/*.*\\*/");
|
||||
highlightingRules.append(rule);
|
||||
}
|
||||
|
||||
|
|
@ -191,15 +191,11 @@ void ScriptSyntaxHighlighterPrivate::highlightBlock(const QString &text)
|
|||
// qDebug() << "hightlightBlock called for" << text << previousBlockState() << currentBlock().text();
|
||||
|
||||
foreach(const HighlightingRule &rule, highlightingRules){
|
||||
QRegExp expression(rule.pattern);
|
||||
int index = expression.indexIn(text);
|
||||
while (index >= 0) {
|
||||
int length = expression.matchedLength();
|
||||
if (text.mid(index, length).endsWith(':')) {
|
||||
length--;
|
||||
}
|
||||
setFormat(index, length, rule.format);
|
||||
index = expression.indexIn(text, index + length);
|
||||
QRegularExpression expression(rule.pattern);
|
||||
QRegularExpressionMatchIterator matches = expression.globalMatch(text);
|
||||
while (matches.hasNext()) {
|
||||
QRegularExpressionMatch match = matches.next();
|
||||
setFormat(match.capturedStart(), match.capturedLength(), rule.format);
|
||||
}
|
||||
}
|
||||
if (text.trimmed().startsWith("import")) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue