forked from qt-creator/qt-creator
qmljs: handle js directives .pragma and .import
The directives .pragma and .import are not included in the AST. Their source code locations are not stored in any other place. As a result, when reformatting the source, they simply disappear. This patch keep track of their source code locations, so they are not removed when reformatting the source code. This patch contains also some modification in the lexer that should probably be ported to the qtdeclarative version. Task-number: QTCREATORBUG-13038 Change-Id: I5d568abf02d37a584d4d246939736aaec5af5053 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
@@ -1312,7 +1312,7 @@ bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
|
||||
}
|
||||
|
||||
// we found a .pragma library directive
|
||||
directives->pragmaLibrary();
|
||||
directives->pragmaLibrary(lineNumber, column);
|
||||
|
||||
} else {
|
||||
Q_ASSERT(directiveName == QLatin1String("import"));
|
||||
|
||||
@@ -49,11 +49,14 @@ class Engine;
|
||||
class DiagnosticMessage;
|
||||
|
||||
class QML_PARSER_EXPORT Directives {
|
||||
|
||||
public:
|
||||
virtual ~Directives() {}
|
||||
|
||||
virtual void pragmaLibrary()
|
||||
virtual void pragmaLibrary(int line, int column)
|
||||
{
|
||||
Q_UNUSED(line);
|
||||
Q_UNUSED(column);
|
||||
}
|
||||
|
||||
virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
|
||||
|
||||
@@ -230,7 +230,17 @@ QString Document::componentName() const
|
||||
namespace {
|
||||
class CollectDirectives : public Directives
|
||||
{
|
||||
QString documentPath;
|
||||
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;
|
||||
|
||||
public:
|
||||
CollectDirectives(const QString &documentPath)
|
||||
: documentPath(documentPath)
|
||||
@@ -238,29 +248,41 @@ public:
|
||||
|
||||
{}
|
||||
|
||||
virtual void pragmaLibrary() { isLibrary = true; }
|
||||
virtual void importFile(const QString &jsfile, const QString &module, int line, int column)
|
||||
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
|
||||
{
|
||||
Q_UNUSED(line);
|
||||
Q_UNUSED(column);
|
||||
imports += ImportInfo::pathImport(
|
||||
documentPath, jsfile, LanguageUtils::ComponentVersion(), module);
|
||||
addLocation(line, column);
|
||||
}
|
||||
|
||||
virtual void importModule(const QString &uri, const QString &version, const QString &module,
|
||||
int line, int column)
|
||||
int line, int column) override
|
||||
{
|
||||
Q_UNUSED(line);
|
||||
Q_UNUSED(column);
|
||||
imports += ImportInfo::moduleImport(uri, LanguageUtils::ComponentVersion(version), module);
|
||||
addLocation(line, column);
|
||||
}
|
||||
|
||||
virtual QList<SourceLocation> locations() { return _locations; }
|
||||
|
||||
const QString documentPath;
|
||||
bool isLibrary;
|
||||
QList<ImportInfo> imports;
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
QList<SourceLocation> Document::jsDirectives() const
|
||||
{
|
||||
return _jsdirectives;
|
||||
}
|
||||
|
||||
bool Document::parse_helper(int startToken)
|
||||
{
|
||||
Q_ASSERT(! _engine);
|
||||
@@ -275,8 +297,8 @@ bool Document::parse_helper(int startToken)
|
||||
QString source = _source;
|
||||
lexer.setCode(source, /*line = */ 1, /*qmlMode = */_language.isQmlLikeLanguage());
|
||||
|
||||
CollectDirectives collectDirectives(path());
|
||||
_engine->setDirectives(&collectDirectives);
|
||||
CollectDirectives directives = CollectDirectives(path());
|
||||
_engine->setDirectives(&directives);
|
||||
|
||||
switch (startToken) {
|
||||
case QmlJSGrammar::T_FEED_UI_PROGRAM:
|
||||
@@ -284,6 +306,9 @@ bool Document::parse_helper(int startToken)
|
||||
break;
|
||||
case QmlJSGrammar::T_FEED_JS_PROGRAM:
|
||||
_parsedCorrectly = parser.parseProgram();
|
||||
for (const auto &d: directives.locations()) {
|
||||
_jsdirectives << d;
|
||||
}
|
||||
break;
|
||||
case QmlJSGrammar::T_FEED_JS_EXPRESSION:
|
||||
_parsedCorrectly = parser.parseExpression();
|
||||
@@ -295,7 +320,7 @@ bool Document::parse_helper(int startToken)
|
||||
_ast = parser.rootNode();
|
||||
_diagnosticMessages = parser.diagnosticMessages();
|
||||
|
||||
_bind = new Bind(this, &_diagnosticMessages, collectDirectives.isLibrary, collectDirectives.imports);
|
||||
_bind = new Bind(this, &_diagnosticMessages, directives.isLibrary, directives.imports);
|
||||
|
||||
return _parsedCorrectly;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,8 @@ public:
|
||||
QString path() const;
|
||||
QString componentName() const;
|
||||
|
||||
QList<AST::SourceLocation> jsDirectives() const;
|
||||
|
||||
private:
|
||||
bool parse_helper(int kind);
|
||||
|
||||
@@ -109,6 +111,7 @@ private:
|
||||
QString _path;
|
||||
QString _componentName;
|
||||
QString _source;
|
||||
QList<AST::SourceLocation> _jsdirectives;
|
||||
QWeakPointer<Document> _ptr;
|
||||
QByteArray _fingerprint;
|
||||
int _editorRevision;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "parser/qmljsast_p.h"
|
||||
#include "parser/qmljsastvisitor_p.h"
|
||||
#include "parser/qmljsengine_p.h"
|
||||
#include "parser/qmljslexer_p.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QTextBlock>
|
||||
@@ -118,6 +119,23 @@ public:
|
||||
_hadEmptyLine = false;
|
||||
_binaryExpDepth = 0;
|
||||
|
||||
|
||||
// emit directives
|
||||
const QList<SourceLocation> &directives = _doc->jsDirectives();
|
||||
for (const auto &d: directives) {
|
||||
quint32 line = 1;
|
||||
int i = 0;
|
||||
while (line++ < d.startLine && i++ >= 0)
|
||||
i = _doc->source().indexOf(QChar('\n'), i);
|
||||
quint32 offset = static_cast<quint32>(i) + d.startColumn;
|
||||
int endline = _doc->source().indexOf('\n', static_cast<int>(offset) + 1);
|
||||
int end = endline == -1 ? _doc->source().length() : endline;
|
||||
quint32 length = static_cast<quint32>(end) - offset;
|
||||
out(SourceLocation(offset, length, d.startLine, d.startColumn));
|
||||
}
|
||||
if (!directives.isEmpty())
|
||||
newLine();
|
||||
|
||||
accept(node);
|
||||
|
||||
// emit the final comments
|
||||
|
||||
Reference in New Issue
Block a user