Commit 8cd5592f authored by neis's avatar neis Committed by Commit bot

[parsing] When failing due to variable redeclaration, point at the variable.

We used to point elsewhere, for instance the right-hand-side of an assignment.

Small limitation: Since variable proxies only have a start position, not an end
position, the best we can do is point at the first character.  (We cannot rely
on the scanner's last token position because Declare may be called long after
the variable has been scanned.)

R=adamk@chromium.org
BUG=v8:5572

Review-Url: https://codereview.chromium.org/2447143005
Cr-Commit-Position: refs/heads/master@{#40613}
parent a5ed05aa
......@@ -1475,7 +1475,9 @@ Declaration* Parser::DeclareVariable(const AstRawString* name,
name, NORMAL_VARIABLE, scanner()->location().beg_pos);
Declaration* declaration =
factory()->NewVariableDeclaration(proxy, this->scope(), pos);
Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, CHECK_OK);
Declare(declaration, DeclarationDescriptor::NORMAL, mode, init, ok, nullptr,
scanner()->location().end_pos);
if (!*ok) return nullptr;
return declaration;
}
......@@ -1497,7 +1499,7 @@ Declaration* Parser::DeclareModuleImport(const AstRawString* name, int pos,
Variable* Parser::Declare(Declaration* declaration,
DeclarationDescriptor::Kind declaration_kind,
VariableMode mode, InitializationFlag init, bool* ok,
Scope* scope) {
Scope* scope, int var_end_pos) {
if (scope == nullptr) {
scope = this->scope();
}
......@@ -1506,11 +1508,18 @@ Variable* Parser::Declare(Declaration* declaration,
declaration, mode, init, allow_harmony_restrictive_generators(),
&sloppy_mode_block_scope_function_redefinition, ok);
if (!*ok) {
// If we only have the start position of a proxy, we can't highlight the
// whole variable name. Pretend its length is 1 so that we highlight at
// least the first character.
Scanner::Location loc(declaration->proxy()->position(),
var_end_pos != kNoSourcePosition
? var_end_pos
: declaration->proxy()->position() + 1);
if (declaration_kind == DeclarationDescriptor::NORMAL) {
ReportMessage(MessageTemplate::kVarRedeclaration,
declaration->proxy()->raw_name());
ReportMessageAt(loc, MessageTemplate::kVarRedeclaration,
declaration->proxy()->raw_name());
} else {
ReportMessage(MessageTemplate::kParamDupe);
ReportMessageAt(loc, MessageTemplate::kParamDupe);
}
return nullptr;
}
......
......@@ -468,7 +468,8 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
Variable* Declare(Declaration* declaration,
DeclarationDescriptor::Kind declaration_kind,
VariableMode mode, InitializationFlag init, bool* ok,
Scope* declaration_scope = nullptr);
Scope* declaration_scope = nullptr,
int var_end_pos = kNoSourcePosition);
Declaration* DeclareVariable(const AstRawString* name, VariableMode mode,
int pos, bool* ok);
Declaration* DeclareVariable(const AstRawString* name, VariableMode mode,
......
......@@ -131,8 +131,8 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
// an initial value in the declaration (because they are initialized upon
// entering the function).
const AstRawString* name = pattern->raw_name();
VariableProxy* proxy = factory()->NewVariableProxy(
name, NORMAL_VARIABLE, parser_->scanner()->location().beg_pos);
VariableProxy* proxy =
factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
Declaration* declaration = factory()->NewVariableDeclaration(
proxy, descriptor_->scope, descriptor_->declaration_pos);
Variable* var = parser_->Declare(
......
*%(basename)s:8: SyntaxError: Identifier 'x' has already been declared
export let x = 42;
^^
^
SyntaxError: Identifier 'x' has already been declared
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let foo = 1;
let foo = 2;
*%(basename)s:6: SyntaxError: Identifier 'foo' has already been declared
let foo = 2;
^
SyntaxError: Identifier 'foo' has already been declared
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let foo = 1;
let {bar, foo} = {};
*%(basename)s:6: SyntaxError: Identifier 'foo' has already been declared
let {bar, foo} = {};
^
SyntaxError: Identifier 'foo' has already been declared
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
const {bar, foo} = {};
var [...foo] = [11];
*%(basename)s:6: SyntaxError: Identifier 'foo' has already been declared
var [...foo] = [11];
^
SyntaxError: Identifier 'foo' has already been declared
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment