Parsing of definitions metadata for mime type registering is now in a separate thread (QtConcurrent). Also some clean up.

This commit is contained in:
Leandro Melo
2010-05-11 14:53:24 +02:00
parent 67917cd9a1
commit e5401e941c
26 changed files with 90 additions and 11894 deletions

View File

@@ -47,8 +47,6 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QFileInfo>
#include <QDebug>
using namespace GenericEditor;
using namespace Internal;
@@ -97,7 +95,7 @@ void Editor::configure()
try {
const QString &definitionId =
GenericEditorPlugin::instance()->definitionIdByMimeType(mimeType);
QSharedPointer<HighlightDefinition> definition =
const QSharedPointer<HighlightDefinition> &definition =
GenericEditorPlugin::instance()->definition(definitionId);
Highlighter *highlighter = new Highlighter(definition->initialContext());
@@ -112,9 +110,10 @@ void Editor::configure()
//@todo: It's possible to specify an indenter style in the definition file. However, this
// is not really being used because Kate recommends to configure indentation through
// another editor feature. Maybe we should provide something similar in Creator?
// For now the normal indenter is used.
// another feature. Maybe we should provide something similar in Creator? For now the
// normal indenter is used.
m_indenter.reset(new TextEditor::NormalIndenter);
} catch (const HighlighterException &) {
// No highlighter will be set.
}

View File

@@ -36,11 +36,9 @@
#include "editorfactory.h"
#include <coreplugin/icore.h>
#include <coreplugin/mimedatabase.h>
#include <texteditor/texteditorsettings.h>
#include <utils/qtcassert.h>
#include <cppeditor/cppeditorconstants.h>
#include <qmljseditor/qmljseditorconstants.h>
#include <qtconcurrent/QtConcurrentTools>
#include <QtCore/QtAlgorithms>
#include <QtCore/QtPlugin>
@@ -53,6 +51,8 @@
#include <QtCore/QDir>
#include <QtCore/QList>
#include <QtCore/QRegExp>
#include <QtCore/QFuture>
#include <QtCore/QtConcurrentRun>
#include <QtXml/QXmlSimpleReader>
#include <QtXml/QXmlInputSource>
#include <QtXml/QXmlStreamReader>
@@ -69,8 +69,7 @@ GenericEditorPlugin::GenericEditorPlugin() :
QTC_ASSERT(!m_instance, return);
m_instance = this;
connect(Core::ICore::instance(), SIGNAL(coreOpened()),
this, SLOT(lookforAvailableDefinitions()));
connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(registerMimeTypes()));
}
GenericEditorPlugin::~GenericEditorPlugin()
@@ -158,7 +157,16 @@ const QSharedPointer<HighlightDefinition> &GenericEditorPlugin::definition(const
bool GenericEditorPlugin::isBuildingDefinition(const QString &id) const
{ return m_isBuilding.contains(id); }
void GenericEditorPlugin::lookforAvailableDefinitions()
void GenericEditorPlugin::registerMimeTypes()
{
QFuture<Core::MimeType> future =
QtConcurrent::run(&GenericEditorPlugin::gatherDefinitionsMimeTypes, this);
m_watcher.setFuture(future);
connect(&m_watcher, SIGNAL(resultReadyAt(int)), this, SLOT(registerMimeType(int)));
}
void GenericEditorPlugin::gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &future)
{
QDir definitionsDir(Core::ICore::instance()->resourcePath() +
QLatin1String("/generic-highlighter"));
@@ -167,11 +175,50 @@ void GenericEditorPlugin::lookforAvailableDefinitions()
definitionsDir.setNameFilters(filter);
const QFileInfoList &filesInfo = definitionsDir.entryInfoList();
foreach (const QFileInfo &fileInfo, filesInfo)
parseDefinitionMetadata(fileInfo);
foreach (const QFileInfo &fileInfo, filesInfo) {
QString comment;
QStringList mimeTypes;
QStringList patterns;
parseDefinitionMetadata(fileInfo, &comment, &mimeTypes, &patterns);
// A definition can specify multiple MIME types and file extensions/patterns. However, each
// thing is done with a single string. Then, there is no direct way to tell which patterns
// belong to which MIME types nor whether a MIME type is just an alias for the other.
// Currently, I associate all expressions/patterns with all MIME types from a definition.
static const QStringList textPlain(QLatin1String("text/plain"));
QList<QRegExp> expressions;
foreach (const QString &type, mimeTypes) {
Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByType(type);
if (mimeType.isNull()) {
if (expressions.isEmpty()) {
foreach (const QString &pattern, patterns)
expressions.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard));
}
mimeType.setType(type);
mimeType.setSubClassesOf(textPlain);
mimeType.setComment(comment);
mimeType.setGlobPatterns(expressions);
future.reportResult(mimeType);
}
}
}
}
void GenericEditorPlugin::parseDefinitionMetadata(const QFileInfo &fileInfo)
void GenericEditorPlugin::registerMimeType(int index) const
{
const Core::MimeType &mimeType = m_watcher.resultAt(index);
Core::ICore::instance()->mimeDatabase()->addMimeType(mimeType);
m_factory->m_mimeTypes.append(mimeType.type());
}
void GenericEditorPlugin::parseDefinitionMetadata(const QFileInfo &fileInfo,
QString *comment,
QStringList *mimeTypes,
QStringList *patterns)
{
static const QLatin1Char kSemiColon(';');
static const QLatin1Char kSlash('/');
@@ -194,24 +241,24 @@ void GenericEditorPlugin::parseDefinitionMetadata(const QFileInfo &fileInfo)
reader.name() == kLanguage) {
const QXmlStreamAttributes &attr = reader.attributes();
const QString &name = attr.value(kName).toString();
m_idByName.insert(name, id);
*comment = attr.value(kName).toString();
m_idByName.insert(*comment, id);
const QStringList &patterns =
attr.value(kExtensions).toString().split(kSemiColon, QString::SkipEmptyParts);
*patterns = attr.value(kExtensions).toString().split(kSemiColon,
QString::SkipEmptyParts);
QStringList mimeTypes =
attr.value(kMimeType).toString().split(kSemiColon, QString::SkipEmptyParts);
if (mimeTypes.isEmpty()) {
*mimeTypes = attr.value(kMimeType).toString().split(kSemiColon,
QString::SkipEmptyParts);
if (mimeTypes->isEmpty()) {
// There are definitions which do not specify a MIME type, but specify file
// patterns. Creating an artificial MIME type is a workaround.
QString mimeType(kArtificial);
mimeType.append(kSlash).append(name);
m_idByMimeType.insert(mimeType, id);
mimeTypes.append(mimeType);
QString artificialType(kArtificial);
artificialType.append(kSlash).append(*comment);
m_idByMimeType.insert(artificialType, id);
mimeTypes->append(artificialType);
} else {
foreach (const QString &mimeType, mimeTypes)
m_idByMimeType.insert(mimeType, id);
foreach (const QString &type, *mimeTypes)
m_idByMimeType.insert(type, id);
}
// The priority below should not be confused with the priority used when matching files
@@ -220,7 +267,6 @@ void GenericEditorPlugin::parseDefinitionMetadata(const QFileInfo &fileInfo)
// multiple ones associated with the same MIME type (should not happen in general).
m_priorityComp.m_priorityById.insert(id, attr.value(kPriority).toString().toInt());
registerMimeTypes(name, mimeTypes, patterns);
break;
}
}
@@ -228,35 +274,4 @@ void GenericEditorPlugin::parseDefinitionMetadata(const QFileInfo &fileInfo)
definitionFile.close();
}
void GenericEditorPlugin::registerMimeTypes(const QString &comment,
const QStringList &types,
const QStringList &patterns)
{
static const QStringList textPlain(QLatin1String("text/plain"));
// A definition can specify multiple MIME types and file extensions/patterns. However, each
// thing is done with a single string. Then, there is no direct way to tell which extensions/
// patterns belong to which MIME types nor whether a MIME type is just an alias for the other.
// Currentl y, I associate all expressions/patterns with all MIME types from a definition.
QList<QRegExp> expressions;
foreach (const QString &type, types) {
Core::MimeType mimeType = Core::ICore::instance()->mimeDatabase()->findByType(type);
if (mimeType.isNull()) {
if (expressions.isEmpty()) {
foreach (const QString &pattern, patterns)
expressions.append(QRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard));
}
mimeType.setType(type);
mimeType.setSubClassesOf(textPlain);
mimeType.setComment(comment);
mimeType.setGlobPatterns(expressions);
Core::ICore::instance()->mimeDatabase()->addMimeType(mimeType);
m_factory->m_mimeTypes.append(type);
}
}
}
Q_EXPORT_PLUGIN(GenericEditorPlugin)

View File

@@ -30,27 +30,28 @@
#ifndef GENERICEDITORPLUGIN_H
#define GENERICEDITORPLUGIN_H
#include <coreplugin/mimedatabase.h>
#include <extensionsystem/iplugin.h>
#include <texteditor/texteditoractionhandler.h>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QLatin1String>
#include <QtCore/QHash>
#include <QtCore/QMultiHash>
#include <QtCore/QSet>
#include <QtCore/QSharedPointer>
#include <QtCore/QFutureWatcher>
QT_BEGIN_NAMESPACE
class QFileInfo;
class QStringList;
template <class> class QFutureInterface;
QT_END_NAMESPACE
namespace GenericEditor {
namespace Internal {
class HighlightDefinition;
class HighlightDefinitionMetadata;
class Editor;
class EditorFactory;
@@ -75,17 +76,19 @@ public:
const QSharedPointer<HighlightDefinition> &definition(const QString &id);
private slots:
void lookforAvailableDefinitions();
void registerMimeTypes();
void registerMimeType(int index) const;
private:
Q_DISABLE_COPY(GenericEditorPlugin)
static GenericEditorPlugin *m_instance;
void parseDefinitionMetadata(const QFileInfo &fileInfo);
void registerMimeTypes(const QString &comment,
const QStringList &types,
const QStringList &patterns);
void gatherDefinitionsMimeTypes(QFutureInterface<Core::MimeType> &future);
void parseDefinitionMetadata(const QFileInfo &fileInfo,
QString *comment,
QStringList *mimeTypes,
QStringList *patterns);
struct PriorityCompare
{
@@ -100,6 +103,8 @@ private:
EditorFactory *m_factory;
QFutureWatcher<Core::MimeType> m_watcher;
QHash<QString, QString> m_idByName;
QMultiHash<QString, QString> m_idByMimeType;
QHash<QString, QSharedPointer<HighlightDefinition> > m_definitions;

View File

@@ -109,9 +109,6 @@ private:
QString m_multiLineCommentRegion;
Qt::CaseSensitivity m_keywordCaseSensitivity;
QString m_languageName;
QString m_fileExtensions;
};
} // namespace Internal

View File

@@ -430,13 +430,13 @@ void HighlightDefinitionHandler::processIncludeRules(const QSharedPointer<Contex
// definition they are from.
QString externalName = QString::fromRawData(sourceName.unicode() + 2,
sourceName.length() - 2);
const QString id = GenericEditorPlugin::instance()->definitionIdByName(externalName);
const QString &id = GenericEditorPlugin::instance()->definitionIdByName(externalName);
// If there is an incorrect circular dependency among definitions this is skipped.
if (GenericEditorPlugin::instance()->isBuildingDefinition(id))
continue;
QSharedPointer<HighlightDefinition> externalDefinition =
const QSharedPointer<HighlightDefinition> &externalDefinition =
GenericEditorPlugin::instance()->definition(id);
sourceContext = externalDefinition->initialContext();
} else if (!sourceName.startsWith(kHash)) {

View File

@@ -36,7 +36,6 @@
#include <QtCore/QStringList>
#include <QtGui/QSyntaxHighlighter>
#include <QtGui/QTextBlockUserData>
#include <texteditor/basetextdocumentlayout.h>

View File

@@ -31,10 +31,7 @@
#define ITEMDATA_H
#include <QtCore/QString>
#include <QtGui/QColor>
#include <QtGui/QFont>
#include <QtGui/QTextCharFormat>
namespace GenericEditor {
namespace Internal {