forked from qt-creator/qt-creator
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: Thomas Hartmann <Thomas.Hartmann@digia.com>
This commit is contained in:
@@ -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());
|
||||
foreach (const QString &suffix, jsonSourceTy.suffixes())
|
||||
res[suffix] = Language::Json;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user