2012-10-02 09:12:39 +02:00
|
|
|
/****************************************************************************
|
2010-01-18 13:13:34 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2010-01-18 13:13:34 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** This file is part of Qt Creator.
|
2010-01-18 13:13:34 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
** Commercial License Usage
|
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2016-01-15 14:58:39 +01:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2010-01-18 13:13:34 +01:00
|
|
|
**
|
2016-01-15 14:58:39 +01:00
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
2010-12-17 16:01:08 +01:00
|
|
|
**
|
2012-10-02 09:12:39 +02:00
|
|
|
****************************************************************************/
|
2010-01-18 13:13:34 +01:00
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
#include "qmljsdocument.h"
|
2010-02-02 15:55:17 +01:00
|
|
|
#include "qmljsbind.h"
|
2013-10-16 14:59:28 +02:00
|
|
|
#include "qmljsconstants.h"
|
2013-10-16 15:08:27 +02:00
|
|
|
#include "qmljsimportdependencies.h"
|
2010-01-18 13:13:34 +01:00
|
|
|
#include <qmljs/parser/qmljslexer_p.h>
|
|
|
|
|
#include <qmljs/parser/qmljsparser_p.h>
|
2013-04-03 15:06:24 +02:00
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
|
|
|
|
#include <QCryptographicHash>
|
2012-02-15 10:42:41 +01:00
|
|
|
#include <QDir>
|
2014-07-03 12:38:23 +02:00
|
|
|
#include <QFileInfo>
|
2017-03-09 23:02:32 +01:00
|
|
|
#include <QRegExp>
|
2010-01-18 13:13:34 +01:00
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
#include <algorithm>
|
|
|
|
|
|
2010-01-18 13:13:34 +01:00
|
|
|
using namespace QmlJS;
|
|
|
|
|
using namespace QmlJS::AST;
|
|
|
|
|
|
2010-09-15 15:25:59 +02:00
|
|
|
/*!
|
|
|
|
|
\class QmlJS::Document
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The Document class creates a QML or JavaScript document.
|
2011-11-09 16:02:59 +01:00
|
|
|
\sa Snapshot
|
2010-09-15 15:25:59 +02:00
|
|
|
|
2011-11-09 16:02:59 +01:00
|
|
|
Documents are usually created by the ModelManagerInterface
|
|
|
|
|
and stored in a Snapshot. They allow access to data such as
|
|
|
|
|
the file path, source code, abstract syntax tree and the Bind
|
2010-09-15 15:25:59 +02:00
|
|
|
instance for the document.
|
|
|
|
|
|
|
|
|
|
To make sure unused and outdated documents are removed correctly, Document
|
2011-11-09 16:02:59 +01:00
|
|
|
instances are usually accessed through a shared pointer, see Document::Ptr.
|
2011-11-01 14:01:07 +01:00
|
|
|
|
|
|
|
|
Documents in a Snapshot are immutable: They, or anything reachable through them,
|
|
|
|
|
must not be changed. This allows Documents to be shared freely among threads
|
|
|
|
|
without extra synchronization.
|
2010-09-15 15:25:59 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class QmlJS::LibraryInfo
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The LibraryInfo class creates a QML library.
|
2011-11-09 16:02:59 +01:00
|
|
|
\sa Snapshot
|
2010-09-15 15:25:59 +02:00
|
|
|
|
2011-11-09 16:02:59 +01:00
|
|
|
A LibraryInfo is created when the ModelManagerInterface finds
|
2013-09-06 11:52:53 +02:00
|
|
|
a QML library and parses the qmldir file. The instance holds information about
|
2010-09-15 15:25:59 +02:00
|
|
|
which Components the library provides and which plugins to load.
|
|
|
|
|
|
|
|
|
|
The ModelManager will try to extract detailed information about the types
|
|
|
|
|
defined in the plugins this library loads. Once it is done, the data will
|
|
|
|
|
be available through the metaObjects() function.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
\class QmlJS::Snapshot
|
2013-06-05 14:29:24 +02:00
|
|
|
\brief The Snapshot class holds and offers access to a set of
|
|
|
|
|
Document::Ptr and LibraryInfo instances.
|
2011-11-09 16:02:59 +01:00
|
|
|
\sa Document LibraryInfo
|
2010-09-15 15:25:59 +02:00
|
|
|
|
|
|
|
|
Usually Snapshots are copies of the snapshot maintained and updated by the
|
2011-11-09 16:02:59 +01:00
|
|
|
ModelManagerInterface that updates its instance as parsing
|
2010-09-15 15:25:59 +02:00
|
|
|
threads finish and new information becomes available.
|
|
|
|
|
*/
|
|
|
|
|
|
2014-07-22 19:06:44 +02:00
|
|
|
Document::Document(const QString &fileName, Dialect language)
|
2010-01-18 13:13:34 +01:00
|
|
|
: _engine(0)
|
2010-01-22 10:26:25 +01:00
|
|
|
, _ast(0)
|
2010-02-03 15:59:15 +01:00
|
|
|
, _bind(0)
|
2011-09-09 10:55:11 +02:00
|
|
|
, _fileName(QDir::cleanPath(fileName))
|
2010-07-07 17:52:02 +02:00
|
|
|
, _editorRevision(0)
|
2011-09-09 10:55:11 +02:00
|
|
|
, _language(language)
|
2010-01-18 13:13:34 +01:00
|
|
|
, _parsedCorrectly(false)
|
|
|
|
|
{
|
2010-01-26 17:23:18 +01:00
|
|
|
QFileInfo fileInfo(fileName);
|
2010-04-01 14:42:39 +02:00
|
|
|
_path = QDir::cleanPath(fileInfo.absolutePath());
|
2010-01-27 09:24:49 +01:00
|
|
|
|
2014-07-22 19:06:44 +02:00
|
|
|
if (language.isQmlLikeLanguage()) {
|
2010-01-27 09:24:49 +01:00
|
|
|
_componentName = fileInfo.baseName();
|
|
|
|
|
|
|
|
|
|
if (! _componentName.isEmpty()) {
|
|
|
|
|
// ### TODO: check the component name.
|
|
|
|
|
|
|
|
|
|
if (! _componentName.at(0).isUpper())
|
|
|
|
|
_componentName.clear();
|
|
|
|
|
}
|
2010-01-26 17:23:18 +01:00
|
|
|
}
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
Document::~Document()
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2010-02-03 15:59:15 +01:00
|
|
|
if (_bind)
|
|
|
|
|
delete _bind;
|
|
|
|
|
|
2010-01-18 13:13:34 +01:00
|
|
|
if (_engine)
|
|
|
|
|
delete _engine;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-22 19:06:44 +02:00
|
|
|
Document::MutablePtr Document::create(const QString &fileName, Dialect language)
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2011-11-03 13:47:03 +01:00
|
|
|
Document::MutablePtr doc(new Document(fileName, language));
|
2011-05-04 11:12:45 +02:00
|
|
|
doc->_ptr = doc;
|
2010-01-18 13:13:34 +01:00
|
|
|
return doc;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-04 11:12:45 +02:00
|
|
|
Document::Ptr Document::ptr() const
|
|
|
|
|
{
|
|
|
|
|
return _ptr.toStrongRef();
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 12:56:25 +02:00
|
|
|
bool Document::isQmlDocument() const
|
|
|
|
|
{
|
2014-07-22 19:06:44 +02:00
|
|
|
return _language.isQmlLikeLanguage();
|
2010-03-29 12:56:25 +02:00
|
|
|
}
|
|
|
|
|
|
2014-07-22 19:06:44 +02:00
|
|
|
Dialect Document::language() const
|
2011-09-09 10:55:11 +02:00
|
|
|
{
|
|
|
|
|
return _language;
|
2010-03-29 12:56:25 +02:00
|
|
|
}
|
|
|
|
|
|
2014-07-22 19:06:44 +02:00
|
|
|
void Document::setLanguage(Dialect l)
|
2012-12-06 17:20:58 +01:00
|
|
|
{
|
|
|
|
|
_language = l;
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
QString Document::importId() const
|
|
|
|
|
{
|
2013-11-19 10:42:57 +01:00
|
|
|
return _fileName;
|
2013-11-13 16:31:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QByteArray Document::fingerprint() const
|
|
|
|
|
{
|
|
|
|
|
return _fingerprint;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
AST::UiProgram *Document::qmlProgram() const
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2010-01-22 10:26:25 +01:00
|
|
|
return cast<UiProgram *>(_ast);
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
AST::Program *Document::jsProgram() const
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2010-01-22 10:26:25 +01:00
|
|
|
return cast<Program *>(_ast);
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-01-26 14:53:11 +01:00
|
|
|
AST::ExpressionNode *Document::expression() const
|
|
|
|
|
{
|
|
|
|
|
if (_ast)
|
|
|
|
|
return _ast->expressionCast();
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-19 10:16:57 +01:00
|
|
|
AST::Node *Document::ast() const
|
|
|
|
|
{
|
2010-01-22 10:26:25 +01:00
|
|
|
return _ast;
|
2010-01-19 10:16:57 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-23 12:57:48 +01:00
|
|
|
const QmlJS::Engine *Document::engine() const
|
|
|
|
|
{
|
|
|
|
|
return _engine;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
QList<DiagnosticMessage> Document::diagnosticMessages() const
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
|
|
|
|
return _diagnosticMessages;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
QString Document::source() const
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
|
|
|
|
return _source;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-18 16:15:23 +01:00
|
|
|
void Document::setSource(const QString &source)
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
|
|
|
|
_source = source;
|
2013-11-13 16:31:04 +01:00
|
|
|
QCryptographicHash sha(QCryptographicHash::Sha1);
|
|
|
|
|
sha.addData(source.toUtf8());
|
|
|
|
|
_fingerprint = sha.result();
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-07 17:52:02 +02:00
|
|
|
int Document::editorRevision() const
|
2010-01-25 14:18:53 +01:00
|
|
|
{
|
2010-07-07 17:52:02 +02:00
|
|
|
return _editorRevision;
|
2010-01-25 14:18:53 +01:00
|
|
|
}
|
|
|
|
|
|
2010-07-07 17:52:02 +02:00
|
|
|
void Document::setEditorRevision(int revision)
|
2010-01-25 14:18:53 +01:00
|
|
|
{
|
2010-07-07 17:52:02 +02:00
|
|
|
_editorRevision = revision;
|
2010-01-25 14:18:53 +01:00
|
|
|
}
|
|
|
|
|
|
2010-02-11 10:19:41 +01:00
|
|
|
QString Document::fileName() const
|
|
|
|
|
{
|
|
|
|
|
return _fileName;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Document::path() const
|
|
|
|
|
{
|
|
|
|
|
return _path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString Document::componentName() const
|
|
|
|
|
{
|
|
|
|
|
return _componentName;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-27 15:12:22 +02:00
|
|
|
namespace {
|
|
|
|
|
class CollectDirectives : public Directives
|
|
|
|
|
{
|
2017-10-19 17:14:12 +02:00
|
|
|
void addLocation(int line, int column) {
|
|
|
|
|
const SourceLocation loc = SourceLocation(
|
|
|
|
|
0, // placeholder
|
|
|
|
|
0, // placeholder
|
|
|
|
|
static_cast<quint32>(line),
|
|
|
|
|
static_cast<quint32>(column));
|
|
|
|
|
_locations += loc;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<SourceLocation> _locations;
|
|
|
|
|
|
2011-09-27 15:12:22 +02:00
|
|
|
public:
|
|
|
|
|
CollectDirectives(const QString &documentPath)
|
|
|
|
|
: documentPath(documentPath)
|
|
|
|
|
, isLibrary(false)
|
|
|
|
|
|
|
|
|
|
{}
|
|
|
|
|
|
2017-10-19 17:14:12 +02:00
|
|
|
virtual void pragmaLibrary(int line, int column) override
|
|
|
|
|
{
|
|
|
|
|
isLibrary = true;
|
|
|
|
|
addLocation(line, column);
|
|
|
|
|
}
|
|
|
|
|
virtual void importFile(const QString &jsfile, const QString &module,
|
|
|
|
|
int line, int column) override
|
2011-09-27 15:12:22 +02:00
|
|
|
{
|
|
|
|
|
imports += ImportInfo::pathImport(
|
|
|
|
|
documentPath, jsfile, LanguageUtils::ComponentVersion(), module);
|
2017-10-19 17:14:12 +02:00
|
|
|
addLocation(line, column);
|
2011-09-27 15:12:22 +02:00
|
|
|
}
|
|
|
|
|
|
2016-05-03 11:57:12 +02:00
|
|
|
virtual void importModule(const QString &uri, const QString &version, const QString &module,
|
2017-10-19 17:14:12 +02:00
|
|
|
int line, int column) override
|
2011-09-27 15:12:22 +02:00
|
|
|
{
|
|
|
|
|
imports += ImportInfo::moduleImport(uri, LanguageUtils::ComponentVersion(version), module);
|
2017-10-19 17:14:12 +02:00
|
|
|
addLocation(line, column);
|
2011-09-27 15:12:22 +02:00
|
|
|
}
|
|
|
|
|
|
2017-10-19 17:14:12 +02:00
|
|
|
virtual QList<SourceLocation> locations() { return _locations; }
|
|
|
|
|
|
|
|
|
|
const QString documentPath;
|
2011-09-27 15:12:22 +02:00
|
|
|
bool isLibrary;
|
|
|
|
|
QList<ImportInfo> imports;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
} // anonymous namespace
|
|
|
|
|
|
2017-10-19 17:14:12 +02:00
|
|
|
|
|
|
|
|
QList<SourceLocation> Document::jsDirectives() const
|
|
|
|
|
{
|
|
|
|
|
return _jsdirectives;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-08 21:37:59 +01:00
|
|
|
bool Document::parse_helper(int startToken)
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
|
|
|
|
Q_ASSERT(! _engine);
|
2010-01-22 10:26:25 +01:00
|
|
|
Q_ASSERT(! _ast);
|
2010-02-03 15:59:15 +01:00
|
|
|
Q_ASSERT(! _bind);
|
2010-01-18 13:13:34 +01:00
|
|
|
|
|
|
|
|
_engine = new Engine();
|
|
|
|
|
|
|
|
|
|
Lexer lexer(_engine);
|
|
|
|
|
Parser parser(_engine);
|
|
|
|
|
|
2010-06-15 14:50:16 +02:00
|
|
|
QString source = _source;
|
2014-07-22 19:06:44 +02:00
|
|
|
lexer.setCode(source, /*line = */ 1, /*qmlMode = */_language.isQmlLikeLanguage());
|
2010-01-18 13:13:34 +01:00
|
|
|
|
2017-10-19 17:14:12 +02:00
|
|
|
CollectDirectives directives = CollectDirectives(path());
|
|
|
|
|
_engine->setDirectives(&directives);
|
2011-09-19 14:16:25 +02:00
|
|
|
|
2010-02-08 21:37:59 +01:00
|
|
|
switch (startToken) {
|
|
|
|
|
case QmlJSGrammar::T_FEED_UI_PROGRAM:
|
|
|
|
|
_parsedCorrectly = parser.parse();
|
|
|
|
|
break;
|
|
|
|
|
case QmlJSGrammar::T_FEED_JS_PROGRAM:
|
|
|
|
|
_parsedCorrectly = parser.parseProgram();
|
2017-10-19 17:14:12 +02:00
|
|
|
for (const auto &d: directives.locations()) {
|
|
|
|
|
_jsdirectives << d;
|
|
|
|
|
}
|
2010-02-08 21:37:59 +01:00
|
|
|
break;
|
|
|
|
|
case QmlJSGrammar::T_FEED_JS_EXPRESSION:
|
|
|
|
|
_parsedCorrectly = parser.parseExpression();
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
Q_ASSERT(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_ast = parser.rootNode();
|
2010-01-18 13:13:34 +01:00
|
|
|
_diagnosticMessages = parser.diagnosticMessages();
|
|
|
|
|
|
2017-10-19 17:14:12 +02:00
|
|
|
_bind = new Bind(this, &_diagnosticMessages, directives.isLibrary, directives.imports);
|
2010-02-02 15:55:17 +01:00
|
|
|
|
2010-01-18 13:13:34 +01:00
|
|
|
return _parsedCorrectly;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-29 12:56:25 +02:00
|
|
|
bool Document::parse()
|
|
|
|
|
{
|
|
|
|
|
if (isQmlDocument())
|
|
|
|
|
return parseQml();
|
|
|
|
|
|
|
|
|
|
return parseJavaScript();
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-08 21:37:59 +01:00
|
|
|
bool Document::parseQml()
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2010-02-08 21:37:59 +01:00
|
|
|
return parse_helper(QmlJSGrammar::T_FEED_UI_PROGRAM);
|
|
|
|
|
}
|
2010-02-02 15:55:17 +01:00
|
|
|
|
2010-02-08 21:37:59 +01:00
|
|
|
bool Document::parseJavaScript()
|
|
|
|
|
{
|
|
|
|
|
return parse_helper(QmlJSGrammar::T_FEED_JS_PROGRAM);
|
2010-01-22 10:26:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool Document::parseExpression()
|
|
|
|
|
{
|
2010-02-08 21:37:59 +01:00
|
|
|
return parse_helper(QmlJSGrammar::T_FEED_JS_EXPRESSION);
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-02-03 15:59:15 +01:00
|
|
|
Bind *Document::bind() const
|
2010-02-02 15:55:17 +01:00
|
|
|
{
|
|
|
|
|
return _bind;
|
|
|
|
|
}
|
|
|
|
|
|
2011-05-27 14:51:30 +02:00
|
|
|
LibraryInfo::LibraryInfo(Status status)
|
|
|
|
|
: _status(status)
|
2011-05-12 15:29:00 +02:00
|
|
|
, _dumpStatus(NoTypeInfo)
|
2010-03-18 15:43:33 +01:00
|
|
|
{
|
2013-11-13 16:31:04 +01:00
|
|
|
updateFingerprint();
|
2010-03-18 15:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
LibraryInfo::LibraryInfo(const QmlDirParser &parser, const QByteArray &fingerprint)
|
2011-05-27 14:51:30 +02:00
|
|
|
: _status(Found)
|
2012-07-31 10:12:26 +02:00
|
|
|
, _components(parser.components().values())
|
2010-03-18 15:43:33 +01:00
|
|
|
, _plugins(parser.plugins())
|
2011-09-02 13:25:08 +02:00
|
|
|
, _typeinfos(parser.typeInfos())
|
2013-11-13 16:31:04 +01:00
|
|
|
, _fingerprint(fingerprint)
|
2011-05-12 15:29:00 +02:00
|
|
|
, _dumpStatus(NoTypeInfo)
|
2010-03-18 15:43:33 +01:00
|
|
|
{
|
2013-11-13 16:31:04 +01:00
|
|
|
if (_fingerprint.isEmpty())
|
|
|
|
|
updateFingerprint();
|
2010-03-18 15:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LibraryInfo::~LibraryInfo()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
QByteArray LibraryInfo::calculateFingerprint() const
|
|
|
|
|
{
|
|
|
|
|
QCryptographicHash hash(QCryptographicHash::Sha1);
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&_status), sizeof(_status));
|
|
|
|
|
int len = _components.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
foreach (const QmlDirParser::Component &component, _components) {
|
|
|
|
|
len = component.fileName.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(component.fileName.constData()), len * sizeof(QChar));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&component.majorVersion), sizeof(component.majorVersion));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&component.minorVersion), sizeof(component.minorVersion));
|
|
|
|
|
len = component.typeName.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(component.typeName.constData()), component.typeName.size() * sizeof(QChar));
|
|
|
|
|
int flags = (component.singleton ? (1 << 0) : 0) + (component.internal ? (1 << 1) : 0);
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
|
|
|
|
|
}
|
|
|
|
|
len = _plugins.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
foreach (const QmlDirParser::Plugin &plugin, _plugins) {
|
|
|
|
|
len = plugin.path.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(plugin.path.constData()), len * sizeof(QChar));
|
|
|
|
|
len = plugin.name.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(plugin.name.constData()), len * sizeof(QChar));
|
|
|
|
|
}
|
|
|
|
|
len = _typeinfos.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
foreach (const QmlDirParser::TypeInfo &typeinfo, _typeinfos) {
|
|
|
|
|
len = typeinfo.fileName.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(typeinfo.fileName.constData()), len * sizeof(QChar));
|
|
|
|
|
}
|
|
|
|
|
len = _metaObjects.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
QList<QByteArray> metaFingerprints;
|
|
|
|
|
foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaObject, _metaObjects)
|
|
|
|
|
metaFingerprints.append(metaObject->fingerprint());
|
|
|
|
|
std::sort(metaFingerprints.begin(), metaFingerprints.end());
|
|
|
|
|
foreach (const QByteArray &fp, metaFingerprints)
|
|
|
|
|
hash.addData(fp);
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&_dumpStatus), sizeof(_dumpStatus));
|
|
|
|
|
len = _dumpError.size(); // localization dependent (avoid?)
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(_dumpError.constData()), len * sizeof(QChar));
|
|
|
|
|
|
|
|
|
|
len = _moduleApis.size();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
foreach (const ModuleApiInfo &moduleInfo, _moduleApis)
|
|
|
|
|
moduleInfo.addToHash(hash); // make it order independent?
|
|
|
|
|
|
|
|
|
|
QByteArray res(hash.result());
|
|
|
|
|
res.append('L');
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void LibraryInfo::updateFingerprint()
|
|
|
|
|
{
|
|
|
|
|
_fingerprint = calculateFingerprint();
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-18 13:13:34 +01:00
|
|
|
Snapshot::Snapshot()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Snapshot::~Snapshot()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 15:08:27 +02:00
|
|
|
Snapshot::Snapshot(const Snapshot &o)
|
|
|
|
|
: _documents(o._documents),
|
|
|
|
|
_documentsByPath(o._documentsByPath),
|
|
|
|
|
_libraries(o._libraries),
|
|
|
|
|
_dependencies(o._dependencies)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2011-08-16 14:11:30 +02:00
|
|
|
void Snapshot::insert(const Document::Ptr &document, bool allowInvalid)
|
2010-01-18 13:13:34 +01:00
|
|
|
{
|
2011-08-16 14:11:30 +02:00
|
|
|
if (document && (allowInvalid || document->qmlProgram() || document->jsProgram())) {
|
2010-05-17 12:01:54 +02:00
|
|
|
const QString fileName = document->fileName();
|
|
|
|
|
const QString path = document->path();
|
2010-05-18 13:40:35 +02:00
|
|
|
remove(fileName);
|
2010-08-31 10:23:48 +02:00
|
|
|
_documentsByPath[path].append(document);
|
2010-05-17 12:01:54 +02:00
|
|
|
_documents.insert(fileName, document);
|
2013-11-13 16:31:04 +01:00
|
|
|
CoreImport cImport;
|
|
|
|
|
cImport.importId = document->importId();
|
|
|
|
|
cImport.language = document->language();
|
2013-11-19 10:42:57 +01:00
|
|
|
cImport.possibleExports << Export(ImportKey(ImportType::File, fileName),
|
2014-07-03 12:38:23 +02:00
|
|
|
QString(), true, QFileInfo(fileName).baseName());
|
2013-11-13 16:31:04 +01:00
|
|
|
cImport.fingerprint = document->fingerprint();
|
|
|
|
|
_dependencies.addCoreImport(cImport);
|
2010-04-01 11:27:49 +02:00
|
|
|
}
|
2010-01-18 13:13:34 +01:00
|
|
|
}
|
|
|
|
|
|
2010-03-18 15:43:33 +01:00
|
|
|
void Snapshot::insertLibraryInfo(const QString &path, const LibraryInfo &info)
|
|
|
|
|
{
|
2014-09-02 14:42:51 +02:00
|
|
|
QTC_CHECK(!path.isEmpty());
|
2013-11-13 16:31:04 +01:00
|
|
|
QTC_CHECK(info.fingerprint() == info.calculateFingerprint());
|
2010-04-01 14:42:39 +02:00
|
|
|
_libraries.insert(QDir::cleanPath(path), info);
|
2013-11-19 10:42:57 +01:00
|
|
|
if (!info.wasFound()) return;
|
2013-11-13 16:31:04 +01:00
|
|
|
CoreImport cImport;
|
|
|
|
|
cImport.importId = path;
|
2014-07-22 19:06:44 +02:00
|
|
|
cImport.language = Dialect::AnyLanguage;
|
2013-11-19 10:42:57 +01:00
|
|
|
QSet<ImportKey> packages;
|
2013-11-13 16:31:04 +01:00
|
|
|
foreach (const ModuleApiInfo &moduleInfo, info.moduleApis()) {
|
|
|
|
|
ImportKey iKey(ImportType::Library, moduleInfo.uri, moduleInfo.version.majorVersion(),
|
|
|
|
|
moduleInfo.version.minorVersion());
|
2013-11-19 10:42:57 +01:00
|
|
|
packages.insert(iKey);
|
|
|
|
|
}
|
|
|
|
|
foreach (const LanguageUtils::FakeMetaObject::ConstPtr &metaO, info.metaObjects()) {
|
|
|
|
|
foreach (const LanguageUtils::FakeMetaObject::Export &e, metaO->exports()) {
|
|
|
|
|
ImportKey iKey(ImportType::Library, e.package, e.version.majorVersion(),
|
|
|
|
|
e.version.minorVersion());
|
|
|
|
|
packages.insert(iKey);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList splitPath = path.split(QLatin1Char('/'));
|
2014-07-03 12:33:23 +02:00
|
|
|
QRegExp vNr(QLatin1String("^(.+)\\.([0-9]+)(?:\\.([0-9]+))?$"));
|
|
|
|
|
QRegExp safeName(QLatin1String("^[a-zA-Z_][[a-zA-Z0-9_]*$"));
|
2013-11-19 10:42:57 +01:00
|
|
|
foreach (const ImportKey &importKey, packages) {
|
2014-07-15 14:22:00 +02:00
|
|
|
if (importKey.splitPath.size() == 1 && importKey.splitPath.at(0).isEmpty() && splitPath.length() > 0) {
|
2014-07-03 12:33:23 +02:00
|
|
|
// relocatable
|
|
|
|
|
QStringList myPath = splitPath;
|
2014-07-15 14:22:00 +02:00
|
|
|
if (vNr.indexIn(myPath.last()) == 0)
|
2014-07-03 12:33:23 +02:00
|
|
|
myPath.last() = vNr.cap(1);
|
2014-07-07 19:46:50 +02:00
|
|
|
for (int iPath = myPath.size(); iPath != 1; ) {
|
2014-07-03 12:33:23 +02:00
|
|
|
--iPath;
|
|
|
|
|
if (safeName.indexIn(myPath.at(iPath)) != 0)
|
|
|
|
|
break;
|
2014-08-23 01:19:53 +02:00
|
|
|
ImportKey iKey(ImportType::Library, QStringList(myPath.mid(iPath)).join(QLatin1Char('.')),
|
2014-07-03 12:33:23 +02:00
|
|
|
importKey.majorVersion, importKey.minorVersion);
|
2014-07-15 14:22:00 +02:00
|
|
|
cImport.possibleExports.append(Export(iKey, (iPath == 1) ? QLatin1String("/") :
|
2014-08-23 01:19:53 +02:00
|
|
|
QStringList(myPath.mid(0, iPath)).join(QLatin1Char('/')), true));
|
2014-07-03 12:33:23 +02:00
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
QString requiredPath = QStringList(splitPath.mid(0, splitPath.size() - importKey.splitPath.size()))
|
|
|
|
|
.join(QLatin1String("/"));
|
|
|
|
|
cImport.possibleExports << Export(importKey, requiredPath, true);
|
|
|
|
|
}
|
2013-11-19 10:42:57 +01:00
|
|
|
}
|
2014-07-15 14:22:00 +02:00
|
|
|
if (cImport.possibleExports.isEmpty() && splitPath.size() > 0) {
|
2014-06-30 12:49:06 +02:00
|
|
|
QRegExp vNr(QLatin1String("^(.+)\\.([0-9]+)(?:\\.([0-9]+))?$"));
|
|
|
|
|
QRegExp safeName(QLatin1String("^[a-zA-Z_][[a-zA-Z0-9_]*$"));
|
|
|
|
|
int majorVersion = LanguageUtils::ComponentVersion::NoVersion;
|
|
|
|
|
int minorVersion = LanguageUtils::ComponentVersion::NoVersion;
|
2016-11-01 15:20:22 +01:00
|
|
|
|
|
|
|
|
foreach (const QmlDirParser::Component &component, info.components()) {
|
|
|
|
|
if (component.majorVersion > majorVersion)
|
|
|
|
|
majorVersion = component.majorVersion;
|
|
|
|
|
if (component.minorVersion > minorVersion)
|
|
|
|
|
minorVersion = component.minorVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-30 12:49:06 +02:00
|
|
|
if (vNr.indexIn(splitPath.last()) == 0) {
|
|
|
|
|
splitPath.last() = vNr.cap(1);
|
|
|
|
|
bool ok;
|
|
|
|
|
majorVersion = vNr.cap(2).toInt(&ok);
|
|
|
|
|
if (!ok)
|
|
|
|
|
majorVersion = LanguageUtils::ComponentVersion::NoVersion;
|
|
|
|
|
minorVersion = vNr.cap(3).toInt(&ok);
|
|
|
|
|
if (vNr.cap(3).isEmpty() || !ok)
|
|
|
|
|
minorVersion = LanguageUtils::ComponentVersion::NoVersion;
|
|
|
|
|
}
|
|
|
|
|
|
2014-07-07 19:46:50 +02:00
|
|
|
for (int iPath = splitPath.size(); iPath != 1; ) {
|
2014-06-30 12:49:06 +02:00
|
|
|
--iPath;
|
|
|
|
|
if (safeName.indexIn(splitPath.at(iPath)) != 0)
|
|
|
|
|
break;
|
2014-08-23 01:19:53 +02:00
|
|
|
ImportKey iKey(ImportType::Library, QStringList(splitPath.mid(iPath)).join(QLatin1Char('.')),
|
2014-06-30 12:49:06 +02:00
|
|
|
majorVersion, minorVersion);
|
2014-07-15 14:22:00 +02:00
|
|
|
cImport.possibleExports.append(Export(iKey, (iPath == 1) ? QLatin1String("/") :
|
2014-08-23 01:19:53 +02:00
|
|
|
QStringList(splitPath.mid(0, iPath)).join(QLatin1Char('/')), true));
|
2014-06-30 12:49:06 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-11-19 10:42:57 +01:00
|
|
|
foreach (const QmlDirParser::Component &component, info.components()) {
|
|
|
|
|
foreach (const Export &e, cImport.possibleExports)
|
2014-07-03 12:38:23 +02:00
|
|
|
_dependencies.addExport(component.fileName, e.exportName, e.pathRequired, e.typeName);
|
2013-11-13 16:31:04 +01:00
|
|
|
}
|
2016-02-26 17:28:30 +01:00
|
|
|
|
2013-11-13 16:31:04 +01:00
|
|
|
cImport.fingerprint = info.fingerprint();
|
|
|
|
|
_dependencies.addCoreImport(cImport);
|
2010-03-18 15:43:33 +01:00
|
|
|
}
|
|
|
|
|
|
2010-05-18 13:40:35 +02:00
|
|
|
void Snapshot::remove(const QString &fileName)
|
|
|
|
|
{
|
|
|
|
|
Document::Ptr doc = _documents.value(fileName);
|
|
|
|
|
if (!doc.isNull()) {
|
2010-08-31 10:23:48 +02:00
|
|
|
const QString &path = doc->path();
|
|
|
|
|
|
|
|
|
|
QList<Document::Ptr> docs = _documentsByPath.value(path);
|
|
|
|
|
docs.removeAll(doc);
|
|
|
|
|
_documentsByPath[path] = docs;
|
|
|
|
|
|
2010-05-18 13:40:35 +02:00
|
|
|
_documents.remove(fileName);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-16 15:08:27 +02:00
|
|
|
const QmlJS::ImportDependencies *Snapshot::importDependencies() const
|
|
|
|
|
{
|
|
|
|
|
return &_dependencies;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QmlJS::ImportDependencies *Snapshot::importDependencies()
|
|
|
|
|
{
|
|
|
|
|
return &_dependencies;
|
|
|
|
|
}
|
|
|
|
|
|
2011-11-03 13:47:03 +01:00
|
|
|
Document::MutablePtr Snapshot::documentFromSource(
|
|
|
|
|
const QString &code, const QString &fileName,
|
2014-07-22 19:06:44 +02:00
|
|
|
Dialect language) const
|
2010-02-16 10:36:09 +01:00
|
|
|
{
|
2011-11-03 13:47:03 +01:00
|
|
|
Document::MutablePtr newDoc = Document::create(fileName, language);
|
2010-02-16 10:36:09 +01:00
|
|
|
|
Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
# skip ast (excluding paste, astpath, and canv'ast'imer)
next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
s = File.read(file)
next if s.include?('qlalr')
orig = s.dup
s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
res = $&
if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
res
else
res.gsub!('} else', 'else')
res.gsub!(/\n +} *\n/m, "\n")
res.gsub(/ *{$/, '')
end
}
s.gsub!(/ *$/, '')
File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
2013-01-08 03:32:53 +02:00
|
|
|
if (Document::Ptr thisDocument = document(fileName))
|
2010-07-07 17:52:02 +02:00
|
|
|
newDoc->_editorRevision = thisDocument->_editorRevision;
|
2010-02-16 10:36:09 +01:00
|
|
|
|
|
|
|
|
newDoc->setSource(code);
|
|
|
|
|
return newDoc;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-01 14:42:39 +02:00
|
|
|
Document::Ptr Snapshot::document(const QString &fileName) const
|
|
|
|
|
{
|
|
|
|
|
return _documents.value(QDir::cleanPath(fileName));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QList<Document::Ptr> Snapshot::documentsInDirectory(const QString &path) const
|
|
|
|
|
{
|
2010-08-31 10:23:48 +02:00
|
|
|
return _documentsByPath.value(QDir::cleanPath(path));
|
2010-04-01 14:42:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LibraryInfo Snapshot::libraryInfo(const QString &path) const
|
|
|
|
|
{
|
|
|
|
|
return _libraries.value(QDir::cleanPath(path));
|
|
|
|
|
}
|
2013-11-13 16:31:04 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
void ModuleApiInfo::addToHash(QCryptographicHash &hash) const
|
|
|
|
|
{
|
|
|
|
|
int len = uri.length();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(uri.constData()), len * sizeof(QChar));
|
|
|
|
|
version.addToHash(hash);
|
|
|
|
|
len = cppName.length();
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
|
|
|
|
|
hash.addData(reinterpret_cast<const char *>(cppName.constData()), len * sizeof(QChar));
|
|
|
|
|
}
|