Commit a8ea0a07 authored by Fawzi Mohamed's avatar Fawzi Mohamed

qmljs: generalize language treatement

* better support qbs and similar non QtQuick qml languages
* begin to clean and migrate things from ModelManager to
  ModelManagerInterface

Change-Id: Ifa39dc1e4c568e9e21307f4913dcb5989e80420f
Reviewed-by: default avatarThomas Hartmann <Thomas.Hartmann@digia.com>
parent a8e8c5fe
......@@ -137,6 +137,34 @@ bool Document::isQmlLikeOrJsLanguage(Language::Enum language)
}
}
QList<Language::Enum> Document::companionLanguages(Language::Enum language)
{
QList<Language::Enum> langs;
langs << language;
switch (language) {
case Language::JavaScript:
case Language::Json:
case Language::QmlProject:
case Language::QmlTypeInfo:
break;
case Language::QmlQbs:
langs << Language::JavaScript;
break;
case Language::Qml:
langs << Language::QmlQtQuick1 << Language::QmlQtQuick2 << Language::JavaScript;
break;
case Language::QmlQtQuick1:
case Language::QmlQtQuick2:
langs << Language::Qml << Language::JavaScript;
break;
case Language::Unknown:
langs << Language::JavaScript << Language::Json << Language::QmlProject << Language:: QmlQbs
<< Language::QmlTypeInfo << Language::QmlQtQuick1 << Language::QmlQtQuick2 ;
break;
}
return langs;
}
Document::Document(const QString &fileName, Language::Enum language)
: _engine(0)
, _ast(0)
......@@ -177,19 +205,6 @@ Document::MutablePtr Document::create(const QString &fileName, Language::Enum la
return doc;
}
Language::Enum Document::guessLanguageFromSuffix(const QString &fileName)
{
if (fileName.endsWith(QLatin1String(".qml"), Qt::CaseInsensitive))
return Language::Qml;
if (fileName.endsWith(QLatin1String(".qbs"), Qt::CaseInsensitive))
return Language::QmlQbs;
if (fileName.endsWith(QLatin1String(".js"), Qt::CaseInsensitive))
return Language::JavaScript;
if (fileName.endsWith(QLatin1String(".json"), Qt::CaseInsensitive))
return Language::Json;
return Language::Unknown;
}
Document::Ptr Document::ptr() const
{
return _ptr.toStrongRef();
......
......@@ -56,6 +56,7 @@ public:
static bool isQmlLikeLanguage(Language::Enum languge);
static bool isFullySupportedLanguage(Language::Enum language);
static bool isQmlLikeOrJsLanguage(Language::Enum language);
static QList<Language::Enum> companionLanguages(Language::Enum language);
protected:
Document(const QString &fileName, Language::Enum language);
......@@ -63,7 +64,6 @@ public:
~Document();
static MutablePtr create(const QString &fileName, Language::Enum language);
static Language::Enum guessLanguageFromSuffix(const QString &fileName);
Document::Ptr ptr() const;
......
......@@ -330,7 +330,7 @@ Import LinkPrivate::importFileOrDirectory(Document::Ptr doc, const ImportInfo &i
->filesInQrcPath(path));
while (iter.hasNext()) {
iter.next();
if (Document::isQmlLikeLanguage(Document::guessLanguageFromSuffix(iter.key()))) {
if (Document::isQmlLikeLanguage(ModelManagerInterface::guessLanguageOfFile(iter.key()))) {
Document::Ptr importedDoc = snapshot.document(iter.value().at(0));
if (importedDoc && importedDoc->bind()->rootObjectValue()) {
const QString targetName = QFileInfo(iter.key()).baseName();
......
......@@ -29,6 +29,8 @@
#include "qmljsmodelmanagerinterface.h"
#include <QFileInfo>
using namespace QmlJS;
/*!
......@@ -65,8 +67,54 @@ ModelManagerInterface::~ModelManagerInterface()
g_instance = 0;
}
static QHash<QString, Language::Enum> defaultLanguageMapping()
{
QHash<QString, Language::Enum> res;
res[QLatin1String("js")] = Language::JavaScript;
res[QLatin1String("qml")] = Language::Qml;
res[QLatin1String("qmltypes")] = Language::QmlTypeInfo;
res[QLatin1String("qmlproject")] = Language::QmlProject;
res[QLatin1String("json")] = Language::Json;
res[QLatin1String("qbs")] = Language::QmlQbs;
return res;
}
Language::Enum ModelManagerInterface::guessLanguageOfFile(const QString &fileName)
{
QHash<QString, Language::Enum> lMapping;
if (instance())
lMapping = instance()->languageForSuffix();
else
lMapping = defaultLanguageMapping();
const QFileInfo info(fileName);
const QString fileSuffix = info.suffix();
return lMapping.value(fileSuffix, Language::Unknown);
}
QStringList ModelManagerInterface::globPatternsForLanguages(const QList<Language::Enum> languages)
{
QHash<QString, Language::Enum> lMapping;
if (instance())
lMapping = instance()->languageForSuffix();
else
lMapping = defaultLanguageMapping();
QStringList patterns;
QHashIterator<QString,Language::Enum> i(lMapping);
while (i.hasNext()) {
i.next();
if (languages.contains(i.value()))
patterns << QLatin1String("*.") + i.key();
}
return patterns;
}
ModelManagerInterface *ModelManagerInterface::instance()
{
return g_instance;
}
QHash<QString, Language::Enum> ModelManagerInterface::languageForSuffix() const
{
return defaultLanguageMapping();
}
......@@ -139,6 +139,8 @@ public:
ModelManagerInterface(QObject *parent = 0);
virtual ~ModelManagerInterface();
static Language::Enum guessLanguageOfFile(const QString &fileName);
static QStringList globPatternsForLanguages(const QList<Language::Enum> languages);
static ModelManagerInterface *instance();
virtual WorkingCopy workingCopy() const = 0;
......@@ -184,7 +186,6 @@ public:
// Blocks until all parsing threads are done. Used for testing.
virtual void joinAllThreads() = 0;
public slots:
virtual void resetCodeModel() = 0;
......@@ -194,6 +195,8 @@ signals:
void aboutToRemoveFiles(const QStringList &files);
void libraryInfoUpdated(const QString &path, const QmlJS::LibraryInfo &info);
void projectInfoUpdated(const ProjectInfo &pinfo);
protected:
virtual QHash<QString,Language::Enum> languageForSuffix() const;
};
} // namespace QmlJS
......
......@@ -816,7 +816,7 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
if (oldDoc)
language = oldDoc->language();
else
language = QmlJSTools::languageOfFile(fileName);
language = ModelManagerInterface::guessLanguageOfFile(fileName);
Document::MutablePtr newDoc = snapshot.documentFromSource(
it.value().first, fileName, language);
......
......@@ -172,62 +172,28 @@ void QmlJSTools::setupProjectInfoQmlBundles(ModelManagerInterface::ProjectInfo &
static QStringList environmentImportPaths();
static void mergeSuffixes(QStringList &l1, const QStringList &l2)
QHash<QString,QmlJS::Language::Enum> ModelManager::languageForSuffix() const
{
if (!l2.isEmpty())
l1 = l2;
}
QmlJS::Language::Enum QmlJSTools::languageOfFile(const QString &fileName)
{
QStringList jsSuffixes(QLatin1String("js"));
QStringList qmlSuffixes(QLatin1String("qml"));
QStringList qmlProjectSuffixes(QLatin1String("qmlproject"));
QStringList jsonSuffixes(QLatin1String("json"));
QStringList qbsSuffixes(QLatin1String("qbs"));
QHash<QString,QmlJS::Language::Enum> res = ModelManagerInterface::languageForSuffix();
if (ICore::instance()) {
MimeType jsSourceTy = MimeDatabase::findByType(QLatin1String(Constants::JS_MIMETYPE));
mergeSuffixes(jsSuffixes, jsSourceTy.suffixes());
foreach (const QString &suffix, jsSourceTy.suffixes())
res[suffix] = Language::JavaScript;
MimeType qmlSourceTy = MimeDatabase::findByType(QLatin1String(Constants::QML_MIMETYPE));
mergeSuffixes(qmlSuffixes, qmlSourceTy.suffixes());
foreach (const QString &suffix, qmlSourceTy.suffixes())
res[suffix] = Language::Qml;
MimeType qbsSourceTy = MimeDatabase::findByType(QLatin1String(Constants::QBS_MIMETYPE));
mergeSuffixes(qbsSuffixes, qbsSourceTy.suffixes());
foreach (const QString &suffix, qbsSourceTy.suffixes())
res[suffix] = Language::QmlQbs;
MimeType qmlProjectSourceTy = MimeDatabase::findByType(QLatin1String(Constants::QMLPROJECT_MIMETYPE));
mergeSuffixes(qmlProjectSuffixes, qmlProjectSourceTy.suffixes());
foreach (const QString &suffix, qmlProjectSourceTy.suffixes())
res[suffix] = Language::QmlProject;
MimeType jsonSourceTy = MimeDatabase::findByType(QLatin1String(Constants::JSON_MIMETYPE));
mergeSuffixes(jsonSuffixes, jsonSourceTy.suffixes());
}
const QFileInfo info(fileName);
const QString fileSuffix = info.suffix();
if (jsSuffixes.contains(fileSuffix))
return QmlJS::Language::JavaScript;
if (qbsSuffixes.contains(fileSuffix))
return QmlJS::Language::QmlQbs;
if (qmlSuffixes.contains(fileSuffix) || qmlProjectSuffixes.contains(fileSuffix))
return QmlJS::Language::Qml;
if (jsonSuffixes.contains(fileSuffix))
return QmlJS::Language::Json;
return QmlJS::Language::Unknown;
}
QStringList QmlJSTools::qmlAndJsGlobPatterns()
{
QStringList pattern;
if (ICore::instance()) {
MimeType jsSourceTy = MimeDatabase::findByType(QLatin1String(Constants::JS_MIMETYPE));
MimeType qmlSourceTy = MimeDatabase::findByType(QLatin1String(Constants::QML_MIMETYPE));
QStringList pattern;
foreach (const MimeGlobPattern &glob, jsSourceTy.globPatterns())
pattern << glob.pattern();
foreach (const MimeGlobPattern &glob, qmlSourceTy.globPatterns())
pattern << glob.pattern();
} else {
pattern << QLatin1String("*.qml") << QLatin1String("*.js");
foreach (const QString &suffix, jsonSourceTy.suffixes())
res[suffix] = Language::Json;
}
return pattern;
return res;
}
ModelManager::ModelManager(QObject *parent):
......@@ -652,9 +618,9 @@ void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &inf
emit libraryInfoUpdated(path, info);
}
static QStringList qmlFilesInDirectory(const QString &path)
static QStringList filesInDirectoryForLanguages(const QString &path, QList<Language::Enum> languages)
{
const QStringList pattern = qmlAndJsGlobPatterns();
const QStringList pattern = ModelManagerInterface::globPatternsForLanguages(languages);
QStringList files;
const QDir dir(path);
......@@ -671,7 +637,8 @@ static void findNewImplicitImports(const Document::Ptr &doc, const Snapshot &sna
// it's important we also do this for JS files, otherwise the isEmpty check will fail
if (snapshot.documentsInDirectory(doc->path()).isEmpty()) {
if (! scannedPaths->contains(doc->path())) {
*importedFiles += qmlFilesInDirectory(doc->path());
*importedFiles += filesInDirectoryForLanguages(doc->path(),
Document::companionLanguages(doc->language()));
scannedPaths->insert(doc->path());
}
}
......@@ -689,7 +656,8 @@ static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapsho
} else if (import.type() == ImportType::Directory) {
if (snapshot.documentsInDirectory(importName).isEmpty()) {
if (! scannedPaths->contains(importName)) {
*importedFiles += qmlFilesInDirectory(importName);
*importedFiles += filesInDirectoryForLanguages(importName,
Document::companionLanguages(doc->language()));
scannedPaths->insert(importName);
}
}
......@@ -703,7 +671,7 @@ static void findNewFileImports(const Document::Ptr &doc, const Snapshot &snapsho
QMapIterator<QString,QStringList> dirContents(ModelManagerInterface::instance()->filesInQrcPath(importName));
while (dirContents.hasNext()) {
dirContents.next();
if (Document::isQmlLikeOrJsLanguage(Document::guessLanguageFromSuffix(dirContents.key()))) {
if (Document::isQmlLikeOrJsLanguage(ModelManagerInterface::guessLanguageOfFile(dirContents.key()))) {
foreach (const QString &filePath, dirContents.value()) {
if (! snapshot.document(filePath))
*importedFiles += filePath;
......@@ -763,7 +731,8 @@ static bool findNewQmlLibraryInPath(const QString &path,
const QFileInfo componentFileInfo(dir.filePath(component.fileName));
const QString path = QDir::cleanPath(componentFileInfo.absolutePath());
if (! scannedPaths->contains(path)) {
*importedFiles += qmlFilesInDirectory(path);
*importedFiles += filesInDirectoryForLanguages(path,
Document::companionLanguages(Language::Unknown));
scannedPaths->insert(path);
}
}
......@@ -845,7 +814,7 @@ void ModelManager::parseLoop(QSet<QString> &scannedPaths,
const QString fileName = files.at(i);
Language::Enum language = languageOfFile(fileName);
Language::Enum language = guessLanguageOfFile(fileName);
if (language == Language::Unknown) {
if (fileName.endsWith(QLatin1String(".qrc")))
modelManager->updateQrcFile(fileName);
......@@ -982,7 +951,8 @@ void ModelManager::importScan(QFutureInterface<void> &future,
if (!findNewQmlLibraryInPath(toScan.path, snapshot, modelManager, &importedFiles,
&scannedPaths, &newLibraries, true)
&& !libOnly && snapshot.documentsInDirectory(toScan.path).isEmpty())
importedFiles += qmlFilesInDirectory(toScan.path);
importedFiles += filesInDirectoryForLanguages(toScan.path,
Document::companionLanguages(language));
workDone += 1;
future.setProgressValue(progressRange * workDone / totalWork);
if (!importedFiles.isEmpty()) {
......
......@@ -60,9 +60,6 @@ class QrcParser;
namespace QmlJSTools {
QMLJSTOOLS_EXPORT QmlJS::Language::Enum languageOfFile(const QString &fileName);
QMLJSTOOLS_EXPORT QStringList qmlAndJsGlobPatterns();
namespace Internal {
class PluginDumper;
......@@ -197,6 +194,8 @@ private:
PluginDumper *m_pluginDumper;
QFutureSynchronizer<void> m_synchronizer;
QHash<QString, QmlJS::Language::Enum> languageForSuffix() const QTC_OVERRIDE;
};
} // namespace Internal
......
......@@ -124,7 +124,7 @@ QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, const QShare
: RefactoringFile(fileName, data)
{
// the RefactoringFile is invalid if its not for a file with qml or js code
if (languageOfFile(fileName) == Language::Unknown)
if (ModelManagerInterface::guessLanguageOfFile(fileName) == Language::Unknown)
m_fileName.clear();
}
......@@ -142,7 +142,8 @@ Document::Ptr QmlJSRefactoringFile::qmljsDocument() const
const QString name = fileName();
const Snapshot &snapshot = data()->m_snapshot;
Document::MutablePtr newDoc = snapshot.documentFromSource(source, name, languageOfFile(name));
Document::MutablePtr newDoc = snapshot.documentFromSource(source, name,
ModelManagerInterface::guessLanguageOfFile(name));
newDoc->parse();
m_qmljsDocument = newDoc;
}
......
......@@ -129,7 +129,7 @@ void QmlProfilerDetailsRewriter::requestDetailsForLocation(int requestId,
QFileInfo fileInfo(localFile);
if (!fileInfo.exists() || !fileInfo.isReadable())
return;
if (!QmlJS::Document::isQmlLikeLanguage(QmlJSTools::languageOfFile(localFile)))
if (!QmlJS::Document::isQmlLikeLanguage(QmlJS::ModelManagerInterface::guessLanguageOfFile(localFile)))
return;
PendingEvent ev = {location, localFile, requestId};
......
......@@ -36,6 +36,7 @@
#include <QFileInfo>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <qmljs/qmljsreformatter.h>
#include <qmljs/parser/qmljsast_p.h>
......@@ -78,7 +79,7 @@ void tst_Reformatter::test()
{
QFETCH(QString, path);
Document::MutablePtr doc = Document::create(path, Document::guessLanguageFromSuffix(path));
Document::MutablePtr doc = Document::create(path, ModelManagerInterface::guessLanguageOfFile(path));
QFile file(doc->fileName());
file.open(QFile::ReadOnly | QFile::Text);
QString source = QString::fromUtf8(file.readAll());
......
......@@ -30,6 +30,7 @@
#include <qmljs/parser/qmljsast_p.h>
#include <qmljs/parser/qmljsastvisitor_p.h>
#include <qmljs/qmljsdocument.h>
#include <qmljs/qmljsmodelmanagerinterface.h>
#include <QFile>
#include <QList>
......@@ -331,7 +332,7 @@ int main(int argc, char *argv[])
const QByteArray source = file.readAll();
file.close();
Document::MutablePtr doc = Document::create(fileName, Document::guessLanguageFromSuffix(fileName));
Document::MutablePtr doc = Document::create(fileName, ModelManagerInterface::guessLanguageOfFile(fileName));
doc->setSource(QString::fromUtf8(source));
doc->parse();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment