summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFawzi Mohamed <fawzi.mohamed@qt.io>2021-02-03 09:06:09 +0100
committerFawzi Mohamed <fawzi.mohamed@qt.io>2021-02-15 18:22:27 +0100
commit6d51f997df14f2b22c265c5b2fda679ece9edef3 (patch)
tree551889cb0b96998d87c234c6cce657242c4ce954
parenta8685fdb4d57c0ba36d80c395c2ae878595f04da (diff)
Uniformly support shebang
The "qml" tool was the only way of loading QML files that would respect a shebang line. This is problematic as this way you cannot load such files programatically using QQmlComponent, limiting their re-use. Common tools like Qt Creator, but also qmllint, qmlformat, qmlcachegen, etc would not recognize files with shebangs. By moving she-bang support directly in the lexer all tools implicitly support it. Note that we could just as easily support '#' as extra comment character along with //, but here we narrowly add support for in the first line only, as node does (this means that javascript files using she-bang accepted by node, are now accepted also by qml). The only tool needing some adjustments is qmlformat, that has to emit the she-bang again as she-bang and as first line. Add tests for qmlformat, and sprinkle some she-bangs in the other tests just to be sure it doesn't affect anything. Change-Id: I1f6d881c7438bdb23163b5dbe829d59a35d11132 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r--src/qml/parser/qqmljslexer.cpp14
-rw-r--r--tests/auto/qml/qmlcachegen/data/Enums.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/Annotations.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/IfBlocks.qml1
-rw-r--r--tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml2
-rw-r--r--tests/auto/qml/qmlformat/data/QtBug85003.qml2
-rw-r--r--tests/auto/qml/qmlimportscanner/data/ListProperty.qml1
-rw-r--r--tests/auto/qml/qqmlcomponent/data/SpecificComponent/SpecificComponent.qml1
-rw-r--r--tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml1
-rw-r--r--tools/qml/main.cpp20
-rw-r--r--tools/qmlformat/commentastvisitor.h1
-rw-r--r--tools/qmlformat/dumpastvisitor.cpp2
14 files changed, 29 insertions, 20 deletions
diff --git a/src/qml/parser/qqmljslexer.cpp b/src/qml/parser/qqmljslexer.cpp
index 0c4b2ef32f..0e355c54e6 100644
--- a/src/qml/parser/qqmljslexer.cpp
+++ b/src/qml/parser/qqmljslexer.cpp
@@ -768,6 +768,20 @@ again:
else
return scanNumber(ch);
+ case '#':
+ if (_currentLineNumber == 1 && _currentColumnNumber == 2) {
+ // shebang support
+ while (_codePtr <= _endPtr && !isLineTerminator()) {
+ scanChar();
+ }
+ if (_engine) {
+ _engine->addComment(tokenOffset(), _codePtr - _tokenStartPtr - 1,
+ tokenStartLine(), tokenStartColumn());
+ }
+ goto again;
+ }
+ Q_FALLTHROUGH();
+
default: {
uint c = ch.unicode();
bool identifierWithEscapeChars = false;
diff --git a/tests/auto/qml/qmlcachegen/data/Enums.qml b/tests/auto/qml/qmlcachegen/data/Enums.qml
index 830babb73e..5207ef03f0 100644
--- a/tests/auto/qml/qmlcachegen/data/Enums.qml
+++ b/tests/auto/qml/qmlcachegen/data/Enums.qml
@@ -1,3 +1,4 @@
+#!/she-bang
import QtQml 2.0
QtObject {
enum Test {
diff --git a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
index a05c2125dc..ab56b5ce00 100644
--- a/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/Annotations.formatted.qml
@@ -1,3 +1,4 @@
+#!/she-bang
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
diff --git a/tests/auto/qml/qmlformat/data/Annotations.qml b/tests/auto/qml/qmlformat/data/Annotations.qml
index 2d3d7d2cfd..4638d4f7e9 100644
--- a/tests/auto/qml/qmlformat/data/Annotations.qml
+++ b/tests/auto/qml/qmlformat/data/Annotations.qml
@@ -1,3 +1,4 @@
+#!/she-bang
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
index ddba82c312..d89260df5d 100644
--- a/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml
@@ -1,3 +1,4 @@
+#!/she-bang
Item {
function test() {
//// The following if blocks should NOT HAVE braces
diff --git a/tests/auto/qml/qmlformat/data/IfBlocks.qml b/tests/auto/qml/qmlformat/data/IfBlocks.qml
index 505988b238..2140c8246f 100644
--- a/tests/auto/qml/qmlformat/data/IfBlocks.qml
+++ b/tests/auto/qml/qmlformat/data/IfBlocks.qml
@@ -1,3 +1,4 @@
+#!/she-bang
Item {
function test() {
//// The following if blocks should NOT HAVE braces
diff --git a/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml b/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml
index ee42b39571..53e278ab9c 100644
--- a/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml
+++ b/tests/auto/qml/qmlformat/data/QtBug85003.formatted.qml
@@ -1,3 +1,5 @@
+#!/she-bang
+// extra comment
Item {
Component.onCompleted: {
if (3 < 2)
diff --git a/tests/auto/qml/qmlformat/data/QtBug85003.qml b/tests/auto/qml/qmlformat/data/QtBug85003.qml
index 5d039cb9ca..9bbec07ed4 100644
--- a/tests/auto/qml/qmlformat/data/QtBug85003.qml
+++ b/tests/auto/qml/qmlformat/data/QtBug85003.qml
@@ -1,3 +1,5 @@
+#!/she-bang
+// extra comment
Item {
Component.onCompleted:
{
diff --git a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml
index d2bbc58cc5..faeb1bfe5e 100644
--- a/tests/auto/qml/qmlimportscanner/data/ListProperty.qml
+++ b/tests/auto/qml/qmlimportscanner/data/ListProperty.qml
@@ -1,3 +1,4 @@
+#!/she-bang
import QtQuick 2.12
import Things 1.0
diff --git a/tests/auto/qml/qqmlcomponent/data/SpecificComponent/SpecificComponent.qml b/tests/auto/qml/qqmlcomponent/data/SpecificComponent/SpecificComponent.qml
index 0086737970..46f4542df8 100644
--- a/tests/auto/qml/qqmlcomponent/data/SpecificComponent/SpecificComponent.qml
+++ b/tests/auto/qml/qqmlcomponent/data/SpecificComponent/SpecificComponent.qml
@@ -1,3 +1,4 @@
+#!/she-bang
import QtQuick 2.0
Item {
diff --git a/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml b/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml
index adf491c87e..1b413bec36 100644
--- a/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml
+++ b/tests/auto/qml/qqmlcomponent/data/callingQmlContextComponent.qml
@@ -1,3 +1,4 @@
+#!/she-bang
import qqmlcomponenttest 1.0
CallingContextCheckingClass {
}
diff --git a/tools/qml/main.cpp b/tools/qml/main.cpp
index 7e42402dd0..8e5a493bcd 100644
--- a/tools/qml/main.cpp
+++ b/tools/qml/main.cpp
@@ -338,19 +338,6 @@ static void getAppFlags(int argc, char **argv)
#endif // QT_GUI_LIB
}
-bool getFileSansBangLine(const QString &path, QByteArray &output)
-{
- QFile f(path);
- if (!f.open(QFile::ReadOnly | QFile::Text))
- return false;
- output = f.readAll();
- if (output.startsWith("#!")) {//Remove first line in this case (except \n, to avoid disturbing line count)
- output.remove(0, output.indexOf('\n'));
- return true;
- }
- return false;
-}
-
static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
{
QDir dir(directory+"/dummydata", "*.qml");
@@ -603,12 +590,7 @@ int main(int argc, char *argv[])
QUrl url = QUrl::fromUserInput(path, QDir::currentPath(), QUrl::AssumeLocalFile);
if (verboseMode)
printf("qml: loading %s\n", qPrintable(url.toString()));
- QByteArray strippedFile;
- if (getFileSansBangLine(path, strippedFile))
- // QQmlComponent won't resolve it for us: it doesn't know it's a valid file if we loadData
- e.loadData(strippedFile, e.baseUrl().resolved(url));
- else // Errors or no bang line
- e.load(url);
+ e.load(url);
}
if (lw->earlyExit)
diff --git a/tools/qmlformat/commentastvisitor.h b/tools/qmlformat/commentastvisitor.h
index 6ebf8246ba..09bc786985 100644
--- a/tools/qmlformat/commentastvisitor.h
+++ b/tools/qmlformat/commentastvisitor.h
@@ -65,6 +65,7 @@ struct Comment
QList<SourceLocation> m_srcLocations;
+ bool hasSheBang() const { return !m_srcLocations.isEmpty() && m_srcLocations.first().begin() == 0; }
bool isValid() const { return !m_srcLocations.isEmpty(); }
bool isMultiline() const { return m_text.contains("\n"); }
bool isSyntheticMultiline() const { return m_srcLocations.size() > 1; }
diff --git a/tools/qmlformat/dumpastvisitor.cpp b/tools/qmlformat/dumpastvisitor.cpp
index 771814ffd5..723be4e445 100644
--- a/tools/qmlformat/dumpastvisitor.cpp
+++ b/tools/qmlformat/dumpastvisitor.cpp
@@ -129,7 +129,7 @@ QString DumpAstVisitor::formatComment(const Comment &comment) const
if (useMultilineComment)
result += "/*";
- else
+ else if (!comment.hasSheBang())
result += "//";
result += comment.m_text;