forked from qt-creator/qt-creator
Improve Qml code model import handling.
* Fill the snapshot with files that could be imported. * Implement package imports. * The qmldir file is not parsed yet. Reviewed-by: Erik Verbruggen
This commit is contained in:
@@ -671,7 +671,7 @@ int CodeCompletion::startCompletion(TextEditor::ITextEditable *editor)
|
||||
|
||||
// Set up the current scope chain.
|
||||
QList<AST::Node *> astPath = semanticInfo.astPath(editor->position());
|
||||
context.build(astPath , document, snapshot);
|
||||
context.build(astPath , document, snapshot, m_modelManager->importPaths());
|
||||
|
||||
// Search for the operator that triggered the completion.
|
||||
QChar completionOperator;
|
||||
|
||||
@@ -643,6 +643,7 @@ QmlJSTextEditor::QmlJSTextEditor(QWidget *parent) :
|
||||
m_modelManager = ExtensionSystem::PluginManager::instance()->getObject<ModelManagerInterface>();
|
||||
|
||||
if (m_modelManager) {
|
||||
m_semanticHighlighter->setModelManager(m_modelManager);
|
||||
connect(m_modelManager, SIGNAL(documentUpdated(QmlJS::Document::Ptr)),
|
||||
this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr)));
|
||||
}
|
||||
@@ -980,7 +981,8 @@ TextEditor::BaseTextEditor::Link QmlJSTextEditor::findLinkAt(const QTextCursor &
|
||||
|
||||
Interpreter::Engine interp;
|
||||
Interpreter::Context context(&interp);
|
||||
context.build(semanticInfo.astPath(cursorPosition), semanticInfo.document, semanticInfo.snapshot);
|
||||
context.build(semanticInfo.astPath(cursorPosition), semanticInfo.document,
|
||||
semanticInfo.snapshot, m_modelManager->importPaths());
|
||||
|
||||
Evaluate check(&context);
|
||||
const Interpreter::Value *value = check.reference(node);
|
||||
@@ -1266,7 +1268,8 @@ SemanticHighlighter::Source QmlJSTextEditor::currentSource(bool force)
|
||||
|
||||
SemanticHighlighter::SemanticHighlighter(QObject *parent)
|
||||
: QThread(parent),
|
||||
m_done(false)
|
||||
m_done(false),
|
||||
m_modelManager(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1357,8 +1360,16 @@ SemanticInfo SemanticHighlighter::semanticInfo(const Source &source)
|
||||
semanticInfo.snapshot = snapshot;
|
||||
semanticInfo.document = doc;
|
||||
|
||||
Check checker(doc, snapshot);
|
||||
QStringList importPaths;
|
||||
if (m_modelManager)
|
||||
importPaths = m_modelManager->importPaths();
|
||||
Check checker(doc, snapshot, importPaths);
|
||||
semanticInfo.semanticMessages = checker();
|
||||
|
||||
return semanticInfo;
|
||||
}
|
||||
|
||||
void SemanticHighlighter::setModelManager(ModelManagerInterface *modelManager)
|
||||
{
|
||||
m_modelManager = modelManager;
|
||||
}
|
||||
|
||||
@@ -176,6 +176,7 @@ public:
|
||||
};
|
||||
|
||||
void rehighlight(const Source &source);
|
||||
void setModelManager(ModelManagerInterface *modelManager);
|
||||
|
||||
Q_SIGNALS:
|
||||
void changed(const QmlJSEditor::Internal::SemanticInfo &semanticInfo);
|
||||
@@ -193,6 +194,7 @@ private:
|
||||
bool m_done;
|
||||
Source m_source;
|
||||
SemanticInfo m_lastSemanticInfo;
|
||||
ModelManagerInterface *m_modelManager;
|
||||
};
|
||||
|
||||
class QmlJSTextEditor : public TextEditor::BaseTextEditor
|
||||
|
||||
@@ -172,7 +172,7 @@ void HoverHandler::updateHelpIdAndTooltip(TextEditor::ITextEditor *editor, int p
|
||||
|
||||
Interpreter::Engine interp;
|
||||
Interpreter::Context context(&interp);
|
||||
context.build(astPath, qmlDocument, snapshot);
|
||||
context.build(astPath, qmlDocument, snapshot, m_modelManager->importPaths());
|
||||
|
||||
Evaluate check(&context);
|
||||
const Interpreter::Value *value = check(node);
|
||||
|
||||
@@ -39,8 +39,10 @@
|
||||
#include <texteditor/itexteditor.h>
|
||||
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QLibraryInfo>
|
||||
#include <QtConcurrentRun>
|
||||
#include <qtconcurrent/runextensions.h>
|
||||
#include <QTextStream>
|
||||
@@ -51,6 +53,8 @@ using namespace QmlJS;
|
||||
using namespace QmlJSEditor;
|
||||
using namespace QmlJSEditor::Internal;
|
||||
|
||||
static QStringList environmentImportPaths();
|
||||
|
||||
ModelManager::ModelManager(QObject *parent):
|
||||
ModelManagerInterface(parent),
|
||||
m_core(Core::ICore::instance())
|
||||
@@ -63,6 +67,10 @@ ModelManager::ModelManager(QObject *parent):
|
||||
this, SLOT(onDocumentUpdated(QmlJS::Document::Ptr)));
|
||||
|
||||
loadQmlTypeDescriptions();
|
||||
|
||||
m_defaultImportPaths << environmentImportPaths();
|
||||
m_defaultImportPaths << QLibraryInfo::location(QLibraryInfo::ImportsPath);
|
||||
refreshSourceDirectories(m_defaultImportPaths);
|
||||
}
|
||||
|
||||
void ModelManager::loadQmlTypeDescriptions()
|
||||
@@ -124,6 +132,42 @@ QFuture<void> ModelManager::refreshSourceFiles(const QStringList &sourceFiles)
|
||||
return result;
|
||||
}
|
||||
|
||||
void ModelManager::updateSourceDirectories(const QStringList &directories)
|
||||
{
|
||||
refreshSourceDirectories(directories);
|
||||
}
|
||||
|
||||
QFuture<void> ModelManager::refreshSourceDirectories(const QStringList &sourceDirectories)
|
||||
{
|
||||
if (sourceDirectories.isEmpty()) {
|
||||
return QFuture<void>();
|
||||
}
|
||||
|
||||
const QMap<QString, WorkingCopy> workingCopy = buildWorkingCopyList();
|
||||
|
||||
QFuture<void> result = QtConcurrent::run(&ModelManager::parseDirectories,
|
||||
workingCopy, sourceDirectories,
|
||||
this);
|
||||
|
||||
if (m_synchronizer.futures().size() > 10) {
|
||||
QList<QFuture<void> > futures = m_synchronizer.futures();
|
||||
|
||||
m_synchronizer.clearFutures();
|
||||
|
||||
foreach (QFuture<void> future, futures) {
|
||||
if (! (future.isFinished() || future.isCanceled()))
|
||||
m_synchronizer.addFuture(future);
|
||||
}
|
||||
}
|
||||
|
||||
m_synchronizer.addFuture(result);
|
||||
|
||||
m_core->progressManager()->addTask(result, tr("Indexing"),
|
||||
QmlJSEditor::Constants::TASK_INDEX);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
QMap<QString, ModelManager::WorkingCopy> ModelManager::buildWorkingCopyList()
|
||||
{
|
||||
QMap<QString, WorkingCopy> workingCopy;
|
||||
@@ -212,6 +256,32 @@ void ModelManager::parse(QFutureInterface<void> &future,
|
||||
future.setProgressValue(files.size());
|
||||
}
|
||||
|
||||
void ModelManager::parseDirectories(QFutureInterface<void> &future,
|
||||
QMap<QString, WorkingCopy> workingCopy,
|
||||
QStringList directories,
|
||||
ModelManager *modelManager)
|
||||
{
|
||||
Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
|
||||
Core::MimeType jsSourceTy = db->findByType(QLatin1String("application/javascript"));
|
||||
Core::MimeType qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
|
||||
|
||||
QStringList pattern;
|
||||
foreach (const QRegExp &glob, jsSourceTy.globPatterns())
|
||||
pattern << glob.pattern();
|
||||
foreach (const QRegExp &glob, qmlSourceTy.globPatterns())
|
||||
pattern << glob.pattern();
|
||||
|
||||
QStringList importedFiles;
|
||||
foreach (const QString &path, directories) {
|
||||
QDirIterator fileIterator(path, pattern, QDir::Files,
|
||||
QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
|
||||
while (fileIterator.hasNext())
|
||||
importedFiles << fileIterator.next();
|
||||
}
|
||||
|
||||
parse(future, workingCopy, importedFiles, modelManager);
|
||||
}
|
||||
|
||||
// Check whether fileMimeType is the same or extends knownMimeType
|
||||
bool ModelManager::matchesMimeType(const Core::MimeType &fileMimeType, const Core::MimeType &knownMimeType)
|
||||
{
|
||||
@@ -231,3 +301,38 @@ bool ModelManager::matchesMimeType(const Core::MimeType &fileMimeType, const Cor
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ModelManager::setProjectImportPaths(const QStringList &importPaths)
|
||||
{
|
||||
m_projectImportPaths = importPaths;
|
||||
|
||||
refreshSourceDirectories(importPaths);
|
||||
}
|
||||
|
||||
QStringList ModelManager::importPaths() const
|
||||
{
|
||||
QStringList paths;
|
||||
paths << m_projectImportPaths;
|
||||
paths << m_defaultImportPaths;
|
||||
return paths;
|
||||
}
|
||||
|
||||
static QStringList environmentImportPaths()
|
||||
{
|
||||
QStringList paths;
|
||||
|
||||
QByteArray envImportPath = qgetenv("QML_IMPORT_PATH");
|
||||
|
||||
#if defined(Q_OS_WIN)
|
||||
QLatin1Char pathSep(';');
|
||||
#else
|
||||
QLatin1Char pathSep(':');
|
||||
#endif
|
||||
foreach (const QString &path, QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts)) {
|
||||
QString canonicalPath = QDir(path).canonicalPath();
|
||||
if (!canonicalPath.isEmpty() && !paths.contains(canonicalPath))
|
||||
paths.append(canonicalPath);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
@@ -55,9 +55,13 @@ public:
|
||||
|
||||
virtual QmlJS::Snapshot snapshot() const;
|
||||
virtual void updateSourceFiles(const QStringList &files);
|
||||
virtual void updateSourceDirectories(const QStringList &directories);
|
||||
|
||||
void emitDocumentUpdated(QmlJS::Document::Ptr doc);
|
||||
|
||||
virtual void setProjectImportPaths(const QStringList &importPaths);
|
||||
virtual QStringList importPaths() const;
|
||||
|
||||
Q_SIGNALS:
|
||||
void projectPathChanged(const QString &projectPath);
|
||||
void aboutToRemoveFiles(const QStringList &files);
|
||||
@@ -75,6 +79,7 @@ protected:
|
||||
};
|
||||
|
||||
QFuture<void> refreshSourceFiles(const QStringList &sourceFiles);
|
||||
QFuture<void> refreshSourceDirectories(const QStringList &sourceDirectories);
|
||||
QMap<QString, WorkingCopy> buildWorkingCopyList();
|
||||
|
||||
static void parse(QFutureInterface<void> &future,
|
||||
@@ -82,6 +87,11 @@ protected:
|
||||
QStringList files,
|
||||
ModelManager *modelManager);
|
||||
|
||||
static void parseDirectories(QFutureInterface<void> &future,
|
||||
QMap<QString, WorkingCopy> workingCopy,
|
||||
QStringList directories,
|
||||
ModelManager *modelManager);
|
||||
|
||||
void loadQmlTypeDescriptions();
|
||||
|
||||
private:
|
||||
@@ -90,6 +100,8 @@ private:
|
||||
mutable QMutex m_mutex;
|
||||
Core::ICore *m_core;
|
||||
QmlJS::Snapshot _snapshot;
|
||||
QStringList m_projectImportPaths;
|
||||
QStringList m_defaultImportPaths;
|
||||
|
||||
QFutureSynchronizer<void> m_synchronizer;
|
||||
};
|
||||
|
||||
@@ -54,6 +54,10 @@ public:
|
||||
|
||||
virtual QmlJS::Snapshot snapshot() const = 0;
|
||||
virtual void updateSourceFiles(const QStringList &files) = 0;
|
||||
virtual void updateSourceDirectories(const QStringList &directories) = 0;
|
||||
|
||||
virtual void setProjectImportPaths(const QStringList &importPaths) = 0;
|
||||
virtual QStringList importPaths() const = 0;
|
||||
|
||||
signals:
|
||||
void documentUpdated(QmlJS::Document::Ptr doc);
|
||||
|
||||
Reference in New Issue
Block a user