From 6d51f997df14f2b22c265c5b2fda679ece9edef3 Mon Sep 17 00:00:00 2001 From: Fawzi Mohamed Date: Wed, 3 Feb 2021 09:06:09 +0100 Subject: 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 Reviewed-by: Shawn Rutledge --- src/qml/parser/qqmljslexer.cpp | 14 ++++++++++++++ tests/auto/qml/qmlcachegen/data/Enums.qml | 1 + .../qml/qmlformat/data/Annotations.formatted.qml | 1 + tests/auto/qml/qmlformat/data/Annotations.qml | 1 + tests/auto/qml/qmlformat/data/IfBlocks.formatted.qml | 1 + tests/auto/qml/qmlformat/data/IfBlocks.qml | 1 + .../auto/qml/qmlformat/data/QtBug85003.formatted.qml | 2 ++ tests/auto/qml/qmlformat/data/QtBug85003.qml | 2 ++ .../auto/qml/qmlimportscanner/data/ListProperty.qml | 1 + .../data/SpecificComponent/SpecificComponent.qml | 1 + .../data/callingQmlContextComponent.qml | 1 + tools/qml/main.cpp | 20 +------------------- tools/qmlformat/commentastvisitor.h | 1 + tools/qmlformat/dumpastvisitor.cpp | 2 +- 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 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; -- cgit v1.2.3