summaryrefslogtreecommitdiff
path: root/src/plugins/texteditor
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-08-16 09:47:54 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-08-24 11:30:20 +0200
commitc105ae47c1eb38ee24d919f2fee151c05ec852e0 (patch)
treec1da9f81bd4afe447dada731cff317b19edb6873 /src/plugins/texteditor
parent1b9af316a001cfabcfd26c4fee758ed4d7ecf77e (diff)
downloadqt-creator-c105ae47c1eb38ee24d919f2fee151c05ec852e0.tar.gz
QmlJS: Add semantic highlighting.
Change-Id: If9293244075cff1a52801b50cdbb77248ecd21ea Reviewed-on: http://codereview.qt.nokia.com/3310 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
Diffstat (limited to 'src/plugins/texteditor')
-rw-r--r--src/plugins/texteditor/fontsettingspage.cpp7
-rw-r--r--src/plugins/texteditor/fontsettingspage.h2
-rw-r--r--src/plugins/texteditor/semantichighlighter.cpp138
-rw-r--r--src/plugins/texteditor/semantichighlighter.h91
-rw-r--r--src/plugins/texteditor/texteditor.pro6
-rw-r--r--src/plugins/texteditor/texteditorconstants.h11
-rw-r--r--src/plugins/texteditor/texteditorsettings.cpp21
7 files changed, 274 insertions, 2 deletions
diff --git a/src/plugins/texteditor/fontsettingspage.cpp b/src/plugins/texteditor/fontsettingspage.cpp
index 3facc25498..6393019957 100644
--- a/src/plugins/texteditor/fontsettingspage.cpp
+++ b/src/plugins/texteditor/fontsettingspage.cpp
@@ -239,6 +239,13 @@ FormatDescription::FormatDescription(const QString &id, const QString &displayNa
m_format.setForeground(color);
}
+FormatDescription::FormatDescription(const QString &id, const QString &displayName, const Format &format) :
+ m_id(id),
+ m_displayName(displayName),
+ m_format(format)
+{
+}
+
QColor FormatDescription::foreground() const
{
if (m_id == QLatin1String(Constants::C_LINE_NUMBER)) {
diff --git a/src/plugins/texteditor/fontsettingspage.h b/src/plugins/texteditor/fontsettingspage.h
index cc9300a6b8..8fddfbae84 100644
--- a/src/plugins/texteditor/fontsettingspage.h
+++ b/src/plugins/texteditor/fontsettingspage.h
@@ -60,6 +60,8 @@ class TEXTEDITOR_EXPORT FormatDescription
public:
FormatDescription(const QString &id, const QString &displayName,
const QColor &foreground = Qt::black);
+ FormatDescription(const QString &id, const QString &displayName,
+ const Format &format);
QString id() const
{ return m_id; }
diff --git a/src/plugins/texteditor/semantichighlighter.cpp b/src/plugins/texteditor/semantichighlighter.cpp
new file mode 100644
index 0000000000..6c6ad62823
--- /dev/null
+++ b/src/plugins/texteditor/semantichighlighter.cpp
@@ -0,0 +1,138 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#include "semantichighlighter.h"
+
+#include "syntaxhighlighter.h"
+
+#include <utils/qtcassert.h>
+
+#include <QtGui/QTextDocument>
+#include <QtGui/QTextBlock>
+
+using namespace TextEditor;
+using namespace TextEditor::SemanticHighlighter;
+
+void TextEditor::SemanticHighlighter::incrementalApplyExtraAdditionalFormats(
+ SyntaxHighlighter *highlighter,
+ const QFuture<Result> &future,
+ int from, int to,
+ const QHash<int, QTextCharFormat> &kindToFormat)
+{
+ QMap<int, QVector<Result> > blockNumberToResults;
+ for (int i = from; i < to; ++i) {
+ const Result &result = future.resultAt(i);
+ if (!result.line)
+ continue;
+ blockNumberToResults[result.line - 1].append(result);
+ }
+ if (blockNumberToResults.isEmpty())
+ return;
+
+ const int firstResultBlockNumber = blockNumberToResults.constBegin().key();
+
+ // blocks between currentBlockNumber and the last block with results will
+ // be cleaned of additional extra formats if they have no results
+ int currentBlockNumber = 0;
+ for (int i = from - 1; i >= 0; --i) {
+ const Result &result = future.resultAt(i);
+ if (!result.line)
+ continue;
+ const int blockNumber = result.line - 1;
+ if (blockNumber < firstResultBlockNumber) {
+ // stop! found where last format stopped
+ currentBlockNumber = blockNumber + 1;
+ break;
+ } else {
+ // add previous results for the same line to avoid undoing their formats
+ blockNumberToResults[blockNumber].append(result);
+ }
+ }
+
+ QTextDocument *doc = highlighter->document();
+ QTC_ASSERT(currentBlockNumber < doc->blockCount(), return);
+ QTextBlock b = doc->findBlockByNumber(currentBlockNumber);
+
+ QMapIterator<int, QVector<Result> > it(blockNumberToResults);
+ while (b.isValid() && it.hasNext()) {
+ it.next();
+ const int blockNumber = it.key();
+ QTC_ASSERT(blockNumber < doc->blockCount(), return);
+
+ // clear formats of blocks until blockNumber
+ while (currentBlockNumber < blockNumber) {
+ highlighter->setExtraAdditionalFormats(b, QList<QTextLayout::FormatRange>());
+ b = b.next();
+ ++currentBlockNumber;
+ }
+
+ QList<QTextLayout::FormatRange> formats;
+ foreach (const Result &result, it.value()) {
+ QTextLayout::FormatRange formatRange;
+
+ formatRange.format = kindToFormat.value(result.kind);
+ if (!formatRange.format.isValid())
+ continue;
+
+ formatRange.start = result.column - 1;
+ formatRange.length = result.length;
+ formats.append(formatRange);
+ }
+ highlighter->setExtraAdditionalFormats(b, formats);
+ b = b.next();
+ ++currentBlockNumber;
+ }
+}
+
+void TextEditor::SemanticHighlighter::clearExtraAdditionalFormatsUntilEnd(
+ SyntaxHighlighter *highlighter,
+ const QFuture<Result> &future)
+{
+ // find block number of last result
+ int lastBlockNumber = 0;
+ for (int i = future.resultCount() - 1; i >= 0; --i) {
+ const Result &result = future.resultAt(i);
+ if (result.line) {
+ lastBlockNumber = result.line - 1;
+ break;
+ }
+ }
+
+ QTextDocument *doc = highlighter->document();
+ QTC_ASSERT(lastBlockNumber + 1 < doc->blockCount(), return);
+ QTextBlock b = doc->findBlockByNumber(lastBlockNumber + 1);
+
+ while (b.isValid()) {
+ highlighter->setExtraAdditionalFormats(b, QList<QTextLayout::FormatRange>());
+ b = b.next();
+ }
+}
diff --git a/src/plugins/texteditor/semantichighlighter.h b/src/plugins/texteditor/semantichighlighter.h
new file mode 100644
index 0000000000..4abb94ff4a
--- /dev/null
+++ b/src/plugins/texteditor/semantichighlighter.h
@@ -0,0 +1,91 @@
+/**************************************************************************
+**
+** This file is part of Qt Creator
+**
+** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Nokia Corporation (info@qt.nokia.com)
+**
+**
+** GNU Lesser General Public License Usage
+**
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this file.
+** Please review the following information to ensure the GNU Lesser General
+** Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** Other Usage
+**
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at info@qt.nokia.com.
+**
+**************************************************************************/
+
+#ifndef TEXTEDITOR_SEMANTICHIGHLIGHTER_H
+#define TEXTEDITOR_SEMANTICHIGHLIGHTER_H
+
+#include "texteditor_global.h"
+
+#include <QtCore/QHash>
+#include <QtCore/QMap>
+#include <QtCore/QVector>
+#include <QtCore/QFuture>
+#include <QtGui/QTextCharFormat>
+
+QT_BEGIN_NAMESPACE
+class QTextDocument;
+QT_END_NAMESPACE
+
+namespace TextEditor {
+
+class SyntaxHighlighter;
+
+namespace SemanticHighlighter {
+
+class TEXTEDITOR_EXPORT Result {
+public:
+ unsigned line; // 1-based
+ unsigned column; // 1-based
+ unsigned length;
+ int kind;
+
+ Result()
+ : line(0), column(0), length(0), kind(-1) {}
+ Result(unsigned line, unsigned column, unsigned length, int kind)
+ : line(line), column(column), length(length), kind(kind) {}
+};
+
+// Applies the future results [from, to) and applies the extra formats
+// indicated by Result::kind and kindToFormat to the correct location using
+// SyntaxHighlighter::setExtraAdditionalFormats.
+// It is incremental in the sense that it clears the extra additional formats
+// from all lines that have no results between the (from-1).line result and
+// the (to-1).line result.
+// Requires that results of the Future are ordered by line.
+void TEXTEDITOR_EXPORT incrementalApplyExtraAdditionalFormats(
+ SyntaxHighlighter *highlighter,
+ const QFuture<Result> &future,
+ int from, int to,
+ const QHash<int, QTextCharFormat> &kindToFormat);
+
+// Cleans the extra additional formats after the last result of the Future
+// until the end of the document.
+// Requires that results of the Future are ordered by line.
+void TEXTEDITOR_EXPORT clearExtraAdditionalFormatsUntilEnd(
+ SyntaxHighlighter *highlighter,
+ const QFuture<Result> &future);
+
+
+} // namespace SemanticHighlighter
+} // namespace TextEditor
+
+#endif // TEXTEDITOR_SEMANTICHIGHLIGHTER_H
diff --git a/src/plugins/texteditor/texteditor.pro b/src/plugins/texteditor/texteditor.pro
index fdd9382874..114107601f 100644
--- a/src/plugins/texteditor/texteditor.pro
+++ b/src/plugins/texteditor/texteditor.pro
@@ -106,7 +106,8 @@ SOURCES += texteditorplugin.cpp \
tabpreferences.cpp \
icodestylepreferencesfactory.cpp \
tabpreferenceswidget.cpp \
- fallbackselectorwidget.cpp
+ fallbackselectorwidget.cpp \
+ semantichighlighter.cpp
HEADERS += texteditorplugin.h \
textfilewizard.h \
@@ -217,7 +218,8 @@ HEADERS += texteditorplugin.h \
tabpreferences.h \
icodestylepreferencesfactory.h \
tabpreferenceswidget.h \
- fallbackselectorwidget.h
+ fallbackselectorwidget.h \
+ semantichighlighter.h
FORMS += \
displaysettingspage.ui \
diff --git a/src/plugins/texteditor/texteditorconstants.h b/src/plugins/texteditor/texteditorconstants.h
index b355235dec..fb06787a1b 100644
--- a/src/plugins/texteditor/texteditorconstants.h
+++ b/src/plugins/texteditor/texteditorconstants.h
@@ -128,6 +128,17 @@ const char * const C_COMMENT = "Comment";
const char * const C_DOXYGEN_COMMENT = "Doxygen.Comment";
const char * const C_DOXYGEN_TAG = "Doxygen.Tag";
const char * const C_VISUAL_WHITESPACE = "VisualWhitespace";
+const char * const C_QML_LOCAL_ID = "QmlLocalId";
+const char * const C_QML_EXTERNAL_ID = "QmlExternalId";
+const char * const C_QML_TYPE_ID = "QmlTypeId";
+const char * const C_QML_ROOT_OBJECT_PROPERTY = "QmlRootObjectProperty";
+const char * const C_QML_SCOPE_OBJECT_PROPERTY = "QmlScopeObjectProperty";
+const char * const C_QML_EXTERNAL_OBJECT_PROPERTY = "QmlExternalObjectProperty";
+const char * const C_JS_SCOPE_VAR = "JsScopeVar";
+const char * const C_JS_IMPORT_VAR = "JsImportVar";
+const char * const C_JS_GLOBAL_VAR = "JsGlobalVar";
+const char * const C_QML_STATE_NAME = "QmlStateName";
+
const char * const C_DISABLED_CODE = "DisabledCode";
diff --git a/src/plugins/texteditor/texteditorsettings.cpp b/src/plugins/texteditor/texteditorsettings.cpp
index dad9708640..295832d3df 100644
--- a/src/plugins/texteditor/texteditorsettings.cpp
+++ b/src/plugins/texteditor/texteditorsettings.cpp
@@ -146,6 +146,27 @@ TextEditorSettings::TextEditorSettings(QObject *parent)
virtualMethodFormatDescriptor.format().setItalic(true);
formatDescriptions.append(virtualMethodFormatDescriptor);
+ Format qmlLocalNameFormat;
+ qmlLocalNameFormat.setItalic(true);
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_LOCAL_ID), tr("QML Local Id"), qmlLocalNameFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_ROOT_OBJECT_PROPERTY), tr("QML Root Object Property"), qmlLocalNameFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_SCOPE_OBJECT_PROPERTY), tr("QML Scope Object Property"), qmlLocalNameFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_STATE_NAME), tr("QML State Name"), qmlLocalNameFormat));
+
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_TYPE_ID), tr("QML Type Name"), Qt::darkMagenta));
+
+ Format qmlExternalNameFormat = qmlLocalNameFormat;
+ qmlExternalNameFormat.setForeground(Qt::darkBlue);
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_EXTERNAL_ID), tr("QML External Id"), qmlExternalNameFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_QML_EXTERNAL_OBJECT_PROPERTY), tr("QML External Object Property"), qmlExternalNameFormat));
+
+ Format jsFormat;
+ jsFormat.setForeground(QColor(Qt::darkCyan).darker());
+ jsFormat.setItalic(true);
+ formatDescriptions.append(FormatDescription(QLatin1String(C_JS_SCOPE_VAR), tr("JavaScript Scope Var"), jsFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_JS_IMPORT_VAR), tr("JavaScript Import"), jsFormat));
+ formatDescriptions.append(FormatDescription(QLatin1String(C_JS_GLOBAL_VAR), tr("JavaScript Global Var"), jsFormat));
+
formatDescriptions.append(FormatDescription(QLatin1String(C_KEYWORD), tr("Keyword"), Qt::darkYellow));
formatDescriptions.append(FormatDescription(QLatin1String(C_OPERATOR), tr("Operator")));
formatDescriptions.append(FormatDescription(QLatin1String(C_PREPROCESSOR), tr("Preprocessor"), Qt::darkBlue));