QmlJS: Add check for duplicated import

Add a soft check for duplicated Qml/JS imports which
adds a warning when a file contains imports that
duplicate the same URI / version or file path.

Change-Id: Ib9a1f8a90dd3cf469d90e83abc1d748901b1e353
Reviewed-by: Leena Miettinen <riitta-leena.miettinen@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Christian Stenger
2019-12-09 13:13:58 +01:00
parent a57bfda5d8
commit 6b492866af
5 changed files with 34 additions and 2 deletions

View File

@@ -669,6 +669,11 @@
\l{http://linterrors.com/js/the-array-literal-notation-is-preferrable} \l{http://linterrors.com/js/the-array-literal-notation-is-preferrable}
{The array literal notation [] is preferable}. {The array literal notation [] is preferable}.
\row
\li M400
\li Warning
\li Duplicate import
\endtable \endtable
\section1 Resetting the Code Model \section1 Resetting the Code Model

View File

@@ -764,6 +764,26 @@ bool Check::visit(UiProgram *)
return true; return true;
} }
bool Check::visit(UiImport *ast)
{
ShortImportInfo info;
if (auto ver = ast->version)
info.second = LanguageUtils::ComponentVersion(ver->majorVersion, ver->minorVersion);
if (!ast->fileName.isNull()) // it must be a file import
info.first = ast->fileName.toString();
else // no file import - construct full uri
info.first = toString(ast->importUri);
if (m_importInfo.contains(info)) {
SourceLocation location = ast->firstSourceLocation();
location.length = ast->lastSourceLocation().end();
addMessage(WarnDuplicateImport, location, info.first);
}
m_importInfo.append(info);
return true;
}
bool Check::visit(UiObjectInitializer *) bool Check::visit(UiObjectInitializer *)
{ {
QString typeName; QString typeName;

View File

@@ -65,6 +65,7 @@ protected:
void postVisit(AST::Node *ast) override; void postVisit(AST::Node *ast) override;
bool visit(AST::UiProgram *ast) override; bool visit(AST::UiProgram *ast) override;
bool visit(AST::UiImport *ast) override;
bool visit(AST::UiObjectDefinition *ast) override; bool visit(AST::UiObjectDefinition *ast) override;
bool visit(AST::UiObjectBinding *ast) override; bool visit(AST::UiObjectBinding *ast) override;
bool visit(AST::UiScriptBinding *ast) override; bool visit(AST::UiScriptBinding *ast) override;
@@ -136,6 +137,9 @@ private:
QStack<StringSet> m_propertyStack; QStack<StringSet> m_propertyStack;
QStack<QString> m_typeStack; QStack<QString> m_typeStack;
using ShortImportInfo = QPair<QString, LanguageUtils::ComponentVersion>;
QList<ShortImportInfo> m_importInfo;
class MessageTypeAndSuppression class MessageTypeAndSuppression
{ {
public: public:

View File

@@ -240,6 +240,8 @@ StaticAnalysisMessages::StaticAnalysisMessages()
tr("Referencing the parent of the root item is not supported in a Qt Quick UI form.")); tr("Referencing the parent of the root item is not supported in a Qt Quick UI form."));
newMsg(StateCannotHaveChildItem, Error, newMsg(StateCannotHaveChildItem, Error,
tr("A State cannot have a child item (%1)."), 1); tr("A State cannot have a child item (%1)."), 1);
newMsg(WarnDuplicateImport, Warning,
tr("Duplicate import (%1)."), 1);
} }
} // anonymous namespace } // anonymous namespace

View File

@@ -43,7 +43,7 @@ enum Type
{ {
// Changing the numbers can break user code. // Changing the numbers can break user code.
// When adding a new check, also add it to the documentation, currently // When adding a new check, also add it to the documentation, currently
// in creator-editors.qdoc. // in creator-code-syntax.qdoc.
UnknownType = 0, UnknownType = 0,
ErrInvalidEnumValue = 1, ErrInvalidEnumValue = 1,
ErrEnumValueMustBeStringOrNumber = 2, ErrEnumValueMustBeStringOrNumber = 2,
@@ -128,7 +128,8 @@ enum Type
ErrInvalidStringValuePattern = 320, ErrInvalidStringValuePattern = 320,
ErrLongerStringValueExpected = 321, ErrLongerStringValueExpected = 321,
ErrShorterStringValueExpected = 322, ErrShorterStringValueExpected = 322,
ErrInvalidArrayValueLength = 323 ErrInvalidArrayValueLength = 323,
WarnDuplicateImport = 400
}; };
class QMLJS_EXPORT PrototypeMessageData { class QMLJS_EXPORT PrototypeMessageData {