History

jsdoc info on selected auto-complete entry

Thijs Wenker committed 8 years ago

Commit 179c21a1 parent c46a1151 file · +134 −11Browse files

Showing the changes to interface/src/ui/JSConsole.cpp (1 of 1 file). Show all

Unified · Split

interface/src/ui/JSConsole.cpp+134−11
@@ -17,6 +17,7 @@ · 16 unmodified lines
1717 #include <QtConcurrent/QtConcurrentRun>
1818 #include <QStringListModel>
1919 #include <QListView>
20+#include <QToolTip>
2021
2122 #include <shared/QtHelpers.h>
2223 #include <ScriptEngines.h>
@@ -39,6 +40,21 @@ const QString RESULT_ERROR_STYLE = "color: #d13b22;"; · 16 unmodified lines
3940 const QString GUTTER_PREVIOUS_COMMAND = "<span style=\"color: #57b8bb;\">&lt;</span>";
4041 const QString GUTTER_ERROR = "<span style=\"color: #d13b22;\">X</span>";
4142
43+const QString JSDOC_LINE_SEPARATOR = "\r";
44+
45+const QString JSDOC_STYLE =
46+ "<style type=\"text/css\"> \
47+ .code { \
48+ font-family: Consolas, Monaco, 'Andale Mono', monospace \
49+ } \
50+ pre, code { \
51+ display: inline; \
52+ } \
53+ .no-wrap { \
54+ white-space: nowrap; \
55+ } \
56+ </style>";
57+
4258 const QString JSConsole::_consoleFileName { "about:console" };
4359
4460 const QString JSON_KEY = "entries";
@@ -50,7 +66,7 @@ QList<QString> _readLines(const QString& filename) { · 5 unmodified lines
5066 // TODO: check root["version"]
5167 return root[JSON_KEY].toVariant().toStringList();
5268 }
53−
69+
5470 void _writeLines(const QString& filename, const QList<QString>& lines) {
5571 QFile file(filename);
5672 file.open(QFile::WriteOnly);
@@ -62,6 +78,10 @@ void _writeLines(const QString& filename, const QList<QString>& lines) { · 5 unmodified lines
6278 QTextStream(&file) << json;
6379 }
6480
81+QString _jsdocTypeToString(QJsonValue jsdocType) {
82+ return jsdocType.toObject().value("names").toVariant().toStringList().join("/");
83+}
84+
6585 void JSConsole::readAPI() {
6686 QFile file(PathUtils::resourcesPath() + "auto-complete/hifiJSDoc.json");
6787 file.open(QFile::ReadOnly);
@@ -102,7 +122,10 @@ QStandardItemModel* JSConsole::getAutoCompleteModel(const QString& memberOf) { · 34 unmodified lines
102122 foreach(auto doc, _apiDocs) {
103123 auto object = doc.toObject();
104124 auto scope = object.value("scope");
105− if ((memberOfProperty == nullptr && scope.toString() == "global" && object.value("kind").toString() == "namespace") || (memberOfProperty != nullptr && object.value("memberof").toString() == memberOfProperty)) {
125+ if ((memberOfProperty == nullptr && scope.toString() == "global" && object.value("kind").toString() == "namespace") ||
126+ (memberOfProperty != nullptr && object.value("memberof").toString() == memberOfProperty &&
127+ object.value("kind").toString() != "typedef")) {
128+
106129 model->appendRow(getAutoCompleteItem(doc));
107130 }
108131 }
@@ -166,20 +189,119 @@ JSConsole::JSConsole(QWidget* parent, const ScriptEnginePointer& scriptEngine) : · 57 unmodified lines
166189 }
167190
168191 void JSConsole::insertCompletion(const QModelIndex& completion) {
192+ auto jsdocObject = QJsonValue::fromVariant(completion.data(Qt::UserRole + 1)).toObject();
193+ auto kind = jsdocObject.value("kind").toString();
169194 auto completionString = completion.data().toString();
170− QTextCursor tc = _ui->promptTextEdit->textCursor();
195+ if (kind == "function") {
196+ auto params = jsdocObject.value("params").toArray();
197+ // automatically add the parenthesis/parentheses for the functions
198+ completionString += params.isEmpty() ? "()" : "(";
199+ }
200+ QTextCursor textCursor = _ui->promptTextEdit->textCursor();
171201 int extra = completionString.length() - _completer->completionPrefix().length();
172− tc.movePosition(QTextCursor::Left);
173− tc.movePosition(QTextCursor::EndOfWord);
174− tc.insertText(completionString.right(extra));
175− _ui->promptTextEdit->setTextCursor(tc);
202+ textCursor.movePosition(QTextCursor::Left);
203+ textCursor.movePosition(QTextCursor::EndOfWord);
204+ textCursor.insertText(completionString.right(extra));
205+ _ui->promptTextEdit->setTextCursor(textCursor);
176206 }
177207
178208 void JSConsole::highlightedCompletion(const QModelIndex& completion) {
179− qDebug() << "Highlighted " << completion.data().toString();
180209 auto jsdocObject = QJsonValue::fromVariant(completion.data(Qt::UserRole + 1)).toObject();
181−
182− // qDebug() << "Highlighted data " << QJsonDocument(jsdocObject).toJson(QJsonDocument::Compact);
210+ QString memberOf = "";
211+ if (!_completerModule.isEmpty()) {
212+ memberOf = _completerModule + ".";
213+ }
214+ auto name = memberOf + "<b>" + jsdocObject.value("name").toString() + "</b>";
215+ auto description = jsdocObject.value("description").toString();
216+ auto examples = jsdocObject.value("examples").toArray();
217+ auto kind = jsdocObject.value("kind").toString();
218+ QString returnTypeText = "";
219+
220+ QString paramsTable = "";
221+ if (kind == "function") {
222+ auto params = jsdocObject.value("params").toArray();
223+ auto returns = jsdocObject.value("returns");
224+ if (!returns.isUndefined()) {
225+ returnTypeText = _jsdocTypeToString(jsdocObject.value("returns").toArray().at(0).toObject().value("type")) + " ";
226+ }
227+ name += "(";
228+ if (!params.isEmpty()) {
229+ bool hasDefaultParam = false;
230+ bool hasOptionalParam = false;
231+ bool firstItem = true;
232+ foreach(auto param, params) {
233+ auto paramObject = param.toObject();
234+ if (!hasOptionalParam && paramObject.value("optional").toBool(false)) {
235+ hasOptionalParam = true;
236+ name += "<i>[";
237+ }
238+ if (!firstItem) {
239+ name += ", ";
240+ } else {
241+ firstItem = false;
242+ }
243+ name += paramObject.value("name").toString();
244+ if (!hasDefaultParam && !paramObject.value("defaultvalue").isUndefined()) {
245+ hasDefaultParam = true;
246+ }
247+ }
248+ if (hasOptionalParam) {
249+ name += "]</i>";
250+ }
251+
252+ paramsTable += "<table border=\"1\" cellpadding=\"10\"><thead><tr><th>Name</th><th>Type</th>";
253+ if (hasDefaultParam) {
254+ paramsTable += "<th>Default</th>";
255+ }
256+ paramsTable += "<th>Description</th></tr></thead><tbody>";
257+ foreach(auto param, params) {
258+ auto paramObject = param.toObject();
259+ paramsTable += "<tr><td>" + paramObject.value("name").toString() + "</td><td>" +
260+ _jsdocTypeToString(paramObject.value("type")) + "</td><td>";
261+ if (hasDefaultParam) {
262+ paramsTable += paramObject.value("defaultvalue").toVariant().toString() + "</td><td>";
263+ }
264+ paramsTable += paramObject.value("description").toString() + "</td></tr>";
265+ }
266+
267+ paramsTable += "</tbody></table>";
268+ }
269+ name += ")";
270+ } else if (!jsdocObject.value("type").isUndefined()){
271+ returnTypeText = _jsdocTypeToString(jsdocObject.value("type")) + " ";
272+ }
273+ auto popupText = JSDOC_STYLE + "<span class=\"no-wrap\">" + returnTypeText + name + "</span>";
274+ auto descriptionText = "<p>" + description.replace(JSDOC_LINE_SEPARATOR, "<br>") + "</p>";
275+
276+ popupText += descriptionText;
277+ popupText += paramsTable;
278+ auto returns = jsdocObject.value("returns");
279+ if (!returns.isUndefined()) {
280+ foreach(auto returnEntry, returns.toArray()) {
281+ auto returnsObject = returnEntry.toObject();
282+ auto returnsDescription = returnsObject.value("description").toString().replace(JSDOC_LINE_SEPARATOR, "<br>");
283+ popupText += "<h4>Returns</h4><p>" + returnsDescription + "</p><h5>Type</h5><pre><code>" +
284+ _jsdocTypeToString(returnsObject.value("type")) + "</code></pre>";
285+ }
286+ }
287+
288+ if (!examples.isEmpty()) {
289+ popupText += "<h4>Examples</h4>";
290+ foreach(auto example, examples) {
291+ auto exampleText = example.toString();
292+ auto exampleLines = exampleText.split(JSDOC_LINE_SEPARATOR);
293+ foreach(auto exampleLine, exampleLines) {
294+ if (exampleLine.contains("<caption>")) {
295+ popupText += exampleLine.replace("caption>", "h5>");
296+ } else {
297+ popupText += "<pre><code>" + exampleLine + "\n</code></pre>";
298+ }
299+ }
300+ }
301+ }
302+
303+ QToolTip::showText(QPoint(_completer->popup()->pos().x() + _completer->popup()->width(), _completer->popup()->pos().y()),
304+ popupText, _completer->popup());
183305 }
184306
185307 JSConsole::~JSConsole() {
@@ -299,7 +421,7 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { · 113 unmodified lines
299421 case Qt::Key_Space:
300422 case Qt::Key_Enter:
301423 case Qt::Key_Return:
302− insertCompletion(_completer->currentIndex());
424+ insertCompletion(_completer->popup()->currentIndex());
303425 _completer->popup()->hide();
304426 return true;
305427 default:
@@ -401,6 +523,7 @@ bool JSConsole::eventFilter(QObject* sender, QEvent* event) { · 95 unmodified lines
401523 cursorRect.setWidth(_completer->popup()->sizeHintForColumn(0) +
402524 _completer->popup()->verticalScrollBar()->sizeHint().width());
403525 _completer->complete(cursorRect);
526+ highlightedCompletion(_completer->popup()->currentIndex());
404527 return false;
405528 }
406529 }