diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index ea43a4dec86..deb95ea1d3d 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -384,6 +384,7 @@ protected: _possiblyUndeclaredUses.clear(); _seenNonDeclarationStatement = false; _formalParameterNames.clear(); + QTC_ASSERT(_block == 0, _block = 0); } void postVisit(Node *ast) @@ -399,8 +400,11 @@ protected: if (ast->name.isEmpty()) return false; const QString &name = ast->name.toString(); - if (!_declaredFunctions.contains(name) && !_declaredVariables.contains(name)) + if (!_declaredFunctions.contains(name) + && !(_declaredVariables.contains(name) + || _declaredBlockVariables.contains({name, _block}))) { _possiblyUndeclaredUses[name].append(ast->identifierToken); + } return false; } @@ -416,13 +420,26 @@ protected: if (ast->bindingIdentifier.isEmpty() || !ast->isVariableDeclaration()) return true; const QString &name = ast->bindingIdentifier.toString(); - - if (_formalParameterNames.contains(name)) + VariableScope scope = ast->scope; + if (_formalParameterNames.contains(name)) { addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name); - else if (_declaredFunctions.contains(name)) + } else if (_declaredFunctions.contains(name)) { addMessage(WarnAlreadyFunction, ast->identifierToken, name); - else if (_declaredVariables.contains(name)) - addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else if (scope == VariableScope::Let || scope == VariableScope::Const) { + if (_declaredBlockVariables.contains({name, _block})) + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else if (scope == VariableScope::Var) { + if (_declaredVariables.contains(name)) { + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + } else { + for (auto k : _declaredBlockVariables.keys()) { + if (k.first == name) { + addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); + break; + } + } + } + } if (_possiblyUndeclaredUses.contains(name)) { foreach (const SourceLocation &loc, _possiblyUndeclaredUses.value(name)) { @@ -430,7 +447,10 @@ protected: } _possiblyUndeclaredUses.remove(name); } - _declaredVariables[name] = ast; + if (scope == VariableScope::Let || scope == VariableScope::Const) + _declaredBlockVariables[{name, _block}] = ast; + else + _declaredVariables[name] = ast; return true; } @@ -451,7 +471,7 @@ protected: if (_formalParameterNames.contains(name)) addMessage(WarnAlreadyFormalParameter, ast->identifierToken, name); - else if (_declaredVariables.contains(name)) + else if (_declaredVariables.contains(name) || _declaredBlockVariables.contains({name, _block})) addMessage(WarnAlreadyVar, ast->identifierToken, name); else if (_declaredFunctions.contains(name)) addMessage(WarnDuplicateDeclaration, ast->identifierToken, name); @@ -469,6 +489,25 @@ protected: return false; } + bool visit(Block *) override + { + ++_block; + return true; + } + + void endVisit(Block *) override + { + auto it = _declaredBlockVariables.begin(); + auto end = _declaredBlockVariables.end(); + while (it != end) { + if (it.key().second == _block) + it = _declaredBlockVariables.erase(it); + else + ++it; + } + --_block; + } + private: void addMessage(Type type, const SourceLocation &loc, const QString &arg1 = QString()) { @@ -478,9 +517,11 @@ private: QList _messages; QStringList _formalParameterNames; QHash _declaredVariables; + QHash, PatternElement *> _declaredBlockVariables; QHash _declaredFunctions; QHash > _possiblyUndeclaredUses; bool _seenNonDeclarationStatement; + uint _block = 0; }; class IdsThatShouldNotBeUsedInDesigner : public QStringList