QmlJS: Fix wrong warning

Variable declarations made with let or const need
to get evaluated on block level base.

Task-number: QTCREATORBUG-22054
Change-Id: Ia1d353be61c2d9532bc54257c15d00fb33ea156c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
This commit is contained in:
Christian Stenger
2019-05-15 10:52:09 +02:00
parent 95f49285b7
commit 06d8df7ee6

View File

@@ -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<Message> _messages;
QStringList _formalParameterNames;
QHash<QString, PatternElement *> _declaredVariables;
QHash<QPair<QString, uint>, PatternElement *> _declaredBlockVariables;
QHash<QString, FunctionDeclaration *> _declaredFunctions;
QHash<QString, QList<SourceLocation> > _possiblyUndeclaredUses;
bool _seenNonDeclarationStatement;
uint _block = 0;
};
class IdsThatShouldNotBeUsedInDesigner : public QStringList