OSDN Git Service

QmlJS: Use mime types to distinguish qml and js files.
authorChristian Kamm <christian.d.kamm@nokia.com>
Fri, 9 Sep 2011 08:55:11 +0000 (10:55 +0200)
committerChristian Kamm <christian.d.kamm@nokia.com>
Mon, 12 Sep 2011 08:45:53 +0000 (10:45 +0200)
This allows adding patterns to the qml mime type in the options dialog.
Previously they were always parsed as js.

Change-Id: Ifa344fb6ab8cbcda02becef991cf6807615a1caa
Reviewed-on: http://codereview.qt-project.org/4515
Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
14 files changed:
src/libs/qmljs/qmljsdocument.cpp
src/libs/qmljs/qmljsdocument.h
src/plugins/qmldesigner/designercore/filemanager/astobjecttextextractor.cpp
src/plugins/qmldesigner/designercore/filemanager/firstdefinitionfinder.cpp
src/plugins/qmldesigner/designercore/filemanager/objectlengthcalculator.cpp
src/plugins/qmldesigner/designercore/filemanager/qmlrefactoring.cpp
src/plugins/qmldesigner/designercore/model/modeltotextmerger.cpp
src/plugins/qmldesigner/designercore/model/texttomodelmerger.cpp
src/plugins/qmljseditor/qmlexpressionundercursor.cpp
src/plugins/qmljseditor/qmljsfindreferences.cpp
src/plugins/qmljseditor/qmljssemanticinfoupdater.cpp
src/plugins/qmljstools/qmljsmodelmanager.cpp
src/plugins/qmljstools/qmljsmodelmanager.h
src/plugins/qmljstools/qmljsrefactoringchanges.cpp

index 831e9fb..7fb1379 100644 (file)
@@ -83,23 +83,20 @@ using namespace QmlJS::AST;
 */
 
 
-Document::Document(const QString &fileName)
+Document::Document(const QString &fileName, Language language)
     : _engine(0)
     , _pool(0)
     , _ast(0)
     , _bind(0)
-    , _isQmlDocument(false)
+    , _fileName(QDir::cleanPath(fileName))
     , _editorRevision(0)
+    , _language(language)
     , _parsedCorrectly(false)
-    , _fileName(QDir::cleanPath(fileName))
 {
     QFileInfo fileInfo(fileName);
     _path = QDir::cleanPath(fileInfo.absolutePath());
 
-    // ### Should use mime type
-    if (fileInfo.suffix() == QLatin1String("qml")
-            || fileInfo.suffix() == QLatin1String("qmlproject")) {
-        _isQmlDocument = true;
+    if (language == QmlLanguage) {
         _componentName = fileInfo.baseName();
 
         if (! _componentName.isEmpty()) {
@@ -123,9 +120,9 @@ Document::~Document()
         delete _pool;
 }
 
-Document::Ptr Document::create(const QString &fileName)
+Document::Ptr Document::create(const QString &fileName, Language language)
 {
-    Document::Ptr doc(new Document(fileName));
+    Document::Ptr doc(new Document(fileName, language));
     doc->_ptr = doc;
     return doc;
 }
@@ -137,12 +134,17 @@ Document::Ptr Document::ptr() const
 
 bool Document::isQmlDocument() const
 {
-    return _isQmlDocument;
+    return _language == QmlLanguage;
 }
 
 bool Document::isJSDocument() const
 {
-    return ! _isQmlDocument;
+    return _language == JavaScriptLanguage;
+}
+
+Document::Language Document::language() const
+{
+    return _language;
 }
 
 AST::UiProgram *Document::qmlProgram() const
@@ -422,9 +424,10 @@ void Snapshot::remove(const QString &fileName)
 }
 
 Document::Ptr Snapshot::documentFromSource(const QString &code,
-                                           const QString &fileName) const
+                                           const QString &fileName,
+                                           Document::Language language) const
 {
-    Document::Ptr newDoc = Document::create(fileName);
+    Document::Ptr newDoc = Document::create(fileName, language);
 
     if (Document::Ptr thisDocument = document(fileName)) {
         newDoc->_editorRevision = thisDocument->_editorRevision;
index b2f824c..95a9416 100644 (file)
@@ -56,18 +56,26 @@ class QMLJS_EXPORT Document
 public:
     typedef QSharedPointer<Document> Ptr;
 
+    enum Language
+    {
+        QmlLanguage = 0,
+        JavaScriptLanguage = 1,
+        UnknownLanguage = 2
+    };
+
 protected:
-    Document(const QString &fileName);
+    Document(const QString &fileName, Language language);
 
 public:
     ~Document();
 
-    static Document::Ptr create(const QString &fileName);
+    static Document::Ptr create(const QString &fileName, Language language);
 
     Document::Ptr ptr() const;
 
     bool isQmlDocument() const;
     bool isJSDocument() const;
+    Language language() const;
 
     AST::UiProgram *qmlProgram() const;
     AST::Program *jsProgram() const;
@@ -107,15 +115,15 @@ private:
     NodePool *_pool;
     AST::Node *_ast;
     Bind *_bind;
-    bool _isQmlDocument;
-    int _editorRevision;
-    bool _parsedCorrectly;
     QList<QmlJS::DiagnosticMessage> _diagnosticMessages;
     QString _fileName;
     QString _path;
     QString _componentName;
     QString _source;
     QWeakPointer<Document> _ptr;
+    int _editorRevision;
+    Language _language : 2;
+    bool _parsedCorrectly : 1;
 
     // for documentFromSource
     friend class Snapshot;
@@ -211,7 +219,8 @@ public:
     LibraryInfo libraryInfo(const QString &path) const;
 
     Document::Ptr documentFromSource(const QString &code,
-                                     const QString &fileName) const;
+                                     const QString &fileName,
+                                     Document::Language language) const;
 };
 
 } // namespace QmlJS
index f835dc0..14f90ec 100644 (file)
@@ -39,7 +39,7 @@ using namespace QmlDesigner;
 using namespace QmlJS::AST;
 
 ASTObjectTextExtractor::ASTObjectTextExtractor(const QString &text):
-        m_document(Document::create("<ASTObjectTextExtractor>"))
+        m_document(Document::create("<ASTObjectTextExtractor>", Document::QmlLanguage))
 {
     m_document->setSource(text);
     m_document->parseQml();
index 68461eb..fe5a5ee 100644 (file)
@@ -41,7 +41,7 @@ using namespace QmlDesigner;
 using namespace QmlJS::AST;
 
 FirstDefinitionFinder::FirstDefinitionFinder(const QString &text):
-        m_doc(Document::create("<internal>"))
+        m_doc(Document::create("<internal>", Document::QmlLanguage))
 {
     m_doc->setSource(text);
     bool ok = m_doc->parseQml();
index df22fa6..4463345 100644 (file)
@@ -39,7 +39,7 @@ using namespace QmlDesigner;
 using namespace QmlJS::AST;
 
 ObjectLengthCalculator::ObjectLengthCalculator():
-        m_doc(Document::create("<internal>"))
+        m_doc(Document::create("<internal>", Document::QmlLanguage))
 {
 }
 
index eede5d1..e3da259 100644 (file)
@@ -61,7 +61,7 @@ bool QmlRefactoring::reparseDocument()
 
 //    qDebug() << "QmlRefactoring::reparseDocument() new QML source:" << newSource;
 
-    Document::Ptr tmpDocument(Document::create("<ModelToTextMerger>"));
+    Document::Ptr tmpDocument(Document::create("<ModelToTextMerger>", Document::QmlLanguage));
     tmpDocument->setSource(newSource);
 
     if (tmpDocument->parseQml()) {
index 9755448..4bf2d49 100644 (file)
@@ -229,7 +229,7 @@ void ModelToTextMerger::applyChanges()
     if (m_rewriteActions.isEmpty())
         return;
 
-    Document::Ptr tmpDocument(Document::create(QLatin1String("<ModelToTextMerger>")));
+    Document::Ptr tmpDocument(Document::create(QLatin1String("<ModelToTextMerger>"), Document::QmlLanguage));
     tmpDocument->setSource(m_rewriterView->textModifier()->text());
     if (!tmpDocument->parseQml()) {
         qDebug() << "*** Possible problem: QML file wasn't parsed correctly.";
index 55ba512..fa77d1f 100644 (file)
@@ -750,7 +750,7 @@ bool TextToModelMerger::load(const QString &data, DifferenceHandler &differenceH
     try {
         Snapshot snapshot = m_rewriterView->textModifier()->getSnapshot();
         const QString fileName = url.toLocalFile();
-        Document::Ptr doc = Document::create(fileName.isEmpty() ? QLatin1String("<internal>") : fileName);
+        Document::Ptr doc = Document::create(fileName.isEmpty() ? QLatin1String("<internal>") : fileName, Document::QmlLanguage);
         doc->setSource(data);
         doc->parseQml();
 
index 8b9a8a6..60e90b6 100644 (file)
@@ -136,7 +136,7 @@ QmlJS::AST::ExpressionNode *QmlExpressionUnderCursor::operator()(const QTextCurs
     ExpressionUnderCursor expressionUnderCursor;
     _text = expressionUnderCursor(cursor);
 
-    exprDoc = Document::create(QLatin1String("<expression>"));
+    exprDoc = Document::create(QLatin1String("<expression>"), Document::JavaScriptLanguage);
     exprDoc->setSource(_text);
     exprDoc->parseExpression();
 
index d8afb96..8581255 100644 (file)
@@ -51,6 +51,7 @@
 #include <qmljs/qmljscontext.h>
 #include <qmljs/parser/qmljsastvisitor_p.h>
 #include <qmljs/parser/qmljsast_p.h>
+#include <qmljstools/qmljsmodelmanager.h>
 
 #include "qmljseditorconstants.h"
 
@@ -799,11 +800,19 @@ static void find_helper(QFutureInterface<FindReferences::Usage> &future,
     QHashIterator< QString, QPair<QString, int> > it(workingCopy.all());
     while (it.hasNext()) {
         it.next();
-        Document::Ptr oldDoc = snapshot.document(it.key());
+        const QString fileName = it.key();
+        Document::Ptr oldDoc = snapshot.document(fileName);
         if (oldDoc && oldDoc->editorRevision() == it.value().second)
             continue;
 
-        Document::Ptr newDoc = snapshot.documentFromSource(it.key(), it.value().first);
+        Document::Language language;
+        if (oldDoc)
+            language = oldDoc->language();
+        else
+            language = QmlJSTools::languageOfFile(fileName);
+
+        Document::Ptr newDoc = snapshot.documentFromSource(it.value().first, fileName,
+                                                           language);
         newDoc->parse();
         snapshot.insert(newDoc);
     }
index 6ba69bd..8bc7c47 100644 (file)
@@ -37,6 +37,7 @@
 #include <qmljs/qmljscheck.h>
 #include <qmljs/qmljscontext.h>
 #include <qmljs/qmljslink.h>
+#include <qmljstools/qmljsmodelmanager.h>
 
 namespace QmlJSEditor {
 namespace Internal {
@@ -122,7 +123,12 @@ SemanticInfo SemanticInfoUpdater::semanticInfo(const SemanticInfoUpdaterSource &
 
     if (! doc) {
         snapshot = source.snapshot;
-        doc = snapshot.documentFromSource(source.code, source.fileName);
+        QmlJS::Document::Language language;
+        if (m_lastSemanticInfo.document)
+            language = m_lastSemanticInfo.document->language();
+        else
+            language = QmlJSTools::languageOfFile(source.fileName);
+        doc = snapshot.documentFromSource(source.code, source.fileName, language);
         doc->setEditorRevision(source.revision);
         doc->parse();
         snapshot.insert(doc);
index 054776c..aff7cd4 100644 (file)
@@ -71,6 +71,47 @@ using namespace QmlJSTools::Internal;
 
 static QStringList environmentImportPaths();
 
+QmlJS::Document::Language QmlJSTools::languageOfFile(const QString &fileName)
+{
+    QStringList jsSuffixes("js");
+    QStringList qmlSuffixes("qml");
+
+    if (Core::ICore::instance()) {
+        Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
+        Core::MimeType jsSourceTy = db->findByType(Constants::JS_MIMETYPE);
+        jsSuffixes = jsSourceTy.suffixes();
+        Core::MimeType qmlSourceTy = db->findByType(Constants::QML_MIMETYPE);
+        qmlSuffixes = qmlSourceTy.suffixes();
+    }
+
+    const QFileInfo info(fileName);
+    const QString fileSuffix = info.suffix();
+    if (jsSuffixes.contains(fileSuffix))
+        return QmlJS::Document::JavaScriptLanguage;
+    if (qmlSuffixes.contains(fileSuffix))
+        return QmlJS::Document::QmlLanguage;
+    return QmlJS::Document::UnknownLanguage;
+}
+
+QStringList QmlJSTools::qmlAndJsGlobPatterns()
+{
+    QStringList pattern;
+    if (Core::ICore::instance()) {
+        Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
+        Core::MimeType jsSourceTy = db->findByType(Constants::JS_MIMETYPE);
+        Core::MimeType qmlSourceTy = db->findByType(Constants::QML_MIMETYPE);
+
+        QStringList pattern;
+        foreach (const Core::MimeGlobPattern &glob, jsSourceTy.globPatterns())
+            pattern << glob.regExp().pattern();
+        foreach (const Core::MimeGlobPattern &glob, qmlSourceTy.globPatterns())
+            pattern << glob.regExp().pattern();
+    } else {
+        pattern << "*.qml" << "*.js";
+    }
+    return pattern;
+}
+
 ModelManager::ModelManager(QObject *parent):
         ModelManagerInterface(parent),
         m_core(Core::ICore::instance()),
@@ -349,22 +390,7 @@ void ModelManager::updateLibraryInfo(const QString &path, const LibraryInfo &inf
 
 static QStringList qmlFilesInDirectory(const QString &path)
 {
-    QStringList pattern;
-    if (Core::ICore::instance()) {
-        // ### It would suffice to build pattern once. This function needs to be thread-safe.
-        Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
-        Core::MimeType jsSourceTy = db->findByType(Constants::JS_MIMETYPE);
-        Core::MimeType qmlSourceTy = db->findByType(Constants::QML_MIMETYPE);
-
-        QStringList pattern;
-        foreach (const Core::MimeGlobPattern &glob, jsSourceTy.globPatterns())
-            pattern << glob.regExp().pattern();
-        foreach (const Core::MimeGlobPattern &glob, qmlSourceTy.globPatterns())
-            pattern << glob.regExp().pattern();
-    } else {
-        pattern << "*.qml" << "*.js";
-    }
-
+    const QStringList pattern = qmlAndJsGlobPatterns();
     QStringList files;
 
     const QDir dir(path);
@@ -527,15 +553,6 @@ void ModelManager::parse(QFutureInterface<void> &future,
                             ModelManager *modelManager,
                             bool emitDocChangedOnDisk)
 {
-    Core::MimeDatabase *db = 0;
-    Core::MimeType jsSourceTy;
-    Core::MimeType qmlSourceTy;
-    if (Core::ICore::instance()) {
-        db = Core::ICore::instance()->mimeDatabase();
-        jsSourceTy = db->findByType(QLatin1String("application/javascript"));
-        qmlSourceTy = db->findByType(QLatin1String("application/x-qml"));
-    }
-
     int progressRange = files.size();
     future.setProgressRange(0, progressRange);
 
@@ -549,6 +566,10 @@ void ModelManager::parse(QFutureInterface<void> &future,
 
         const QString fileName = files.at(i);
 
+        Document::Language language = languageOfFile(fileName);
+        if (language == Document::UnknownLanguage)
+            continue;
+
         QString contents;
         int documentRevision = 0;
 
@@ -566,7 +587,7 @@ void ModelManager::parse(QFutureInterface<void> &future,
             }
         }
 
-        Document::Ptr doc = Document::create(fileName);
+        Document::Ptr doc = Document::create(fileName, language);
         doc->setEditorRevision(documentRevision);
         doc->setSource(contents);
         doc->parse();
index 4fd7906..e95c65b 100644 (file)
@@ -55,6 +55,10 @@ class CppModelManagerInterface;
 }
 
 namespace QmlJSTools {
+
+QMLJSTOOLS_EXPORT QmlJS::Document::Language languageOfFile(const QString &fileName);
+QMLJSTOOLS_EXPORT QStringList qmlAndJsGlobPatterns();
+
 namespace Internal {
 
 class PluginDumper;
index 0c01f0c..56b9d84 100644 (file)
@@ -33,6 +33,7 @@
 #include "qmljsrefactoringchanges.h"
 #include "qmljsqtstylecodeformatter.h"
 #include "qmljstoolsconstants.h"
+#include "qmljsmodelmanager.h"
 
 #include <qmljs/parser/qmljsast_p.h>
 #include <qmljs/qmljsmodelmanagerinterface.h>
@@ -112,7 +113,11 @@ QmlJSRefactoringChangesData *QmlJSRefactoringChanges::data() const
 
 QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, const QSharedPointer<TextEditor::RefactoringChangesData> &data)
     : RefactoringFile(fileName, data)
-{ }
+{
+    // the RefactoringFile is invalid if its not for a file with qml or js code
+    if (languageOfFile(fileName) == Document::UnknownLanguage)
+        m_fileName.clear();
+}
 
 QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::BaseTextEditorWidget *editor, QmlJS::Document::Ptr document)
     : RefactoringFile(editor)
@@ -128,7 +133,7 @@ Document::Ptr QmlJSRefactoringFile::qmljsDocument() const
         const QString name = fileName();
         const Snapshot &snapshot = data()->m_snapshot;
 
-        m_qmljsDocument = snapshot.documentFromSource(source, name);
+        m_qmljsDocument = snapshot.documentFromSource(source, name, languageOfFile(name));
         m_qmljsDocument->parse();
     }