[torque-ls] Add "goto Definition" support for labels of goto statements
This CL adds navigation support for labels in "goto" statements. Similar to labels listed in the "otherwise" clause of call expression, definitions of such a label can be found in two places: - The signature of the current macro. - A label block of a "try" statement that surrounds the "goto". R=sigurds@chromium.org Bug: v8:8880 Change-Id: I6c5ebea0b0f80b1882e6672bbb0f45196a7201ba Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1594433 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Cr-Commit-Position: refs/heads/master@{#61229}
This commit is contained in:
parent
b452a9ec99
commit
7d17fd465d
@ -569,12 +569,10 @@ struct ContinueStatement : Statement {
|
||||
|
||||
struct GotoStatement : Statement {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(GotoStatement)
|
||||
GotoStatement(SourcePosition pos, std::string label,
|
||||
GotoStatement(SourcePosition pos, Identifier* label,
|
||||
const std::vector<Expression*>& arguments)
|
||||
: Statement(kKind, pos),
|
||||
label(std::move(label)),
|
||||
arguments(std::move(arguments)) {}
|
||||
std::string label;
|
||||
: Statement(kKind, pos), label(label), arguments(std::move(arguments)) {}
|
||||
Identifier* label;
|
||||
std::vector<Expression*> arguments;
|
||||
};
|
||||
|
||||
|
@ -811,13 +811,18 @@ VisitResult ImplementationVisitor::Visit(LocationExpression* expr) {
|
||||
}
|
||||
|
||||
const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
|
||||
LocalLabel* label = LookupLabel(stmt->label);
|
||||
Binding<LocalLabel>* label = LookupLabel(stmt->label->value);
|
||||
size_t parameter_count = label->parameter_types.size();
|
||||
if (stmt->arguments.size() != parameter_count) {
|
||||
ReportError("goto to label has incorrect number of parameters (expected ",
|
||||
parameter_count, " found ", stmt->arguments.size(), ")");
|
||||
}
|
||||
|
||||
if (GlobalContext::collect_language_server_data()) {
|
||||
LanguageServerData::AddDefinition(stmt->label->pos,
|
||||
label->declaration_position());
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
StackRange arguments = assembler().TopRange(0);
|
||||
for (Expression* e : stmt->arguments) {
|
||||
|
@ -890,10 +890,9 @@ base::Optional<ParseResult> MakeContinueStatement(
|
||||
|
||||
base::Optional<ParseResult> MakeGotoStatement(
|
||||
ParseResultIterator* child_results) {
|
||||
auto label = child_results->NextAs<std::string>();
|
||||
auto label = child_results->NextAs<Identifier*>();
|
||||
auto arguments = child_results->NextAs<std::vector<Expression*>>();
|
||||
Statement* result =
|
||||
MakeNode<GotoStatement>(std::move(label), std::move(arguments));
|
||||
Statement* result = MakeNode<GotoStatement>(label, std::move(arguments));
|
||||
return ParseResult{result};
|
||||
}
|
||||
|
||||
@ -1582,7 +1581,7 @@ struct TorqueGrammar : Grammar {
|
||||
Rule({Token("tail"), &callExpression}, MakeTailCallStatement),
|
||||
Rule({Token("break")}, MakeBreakStatement),
|
||||
Rule({Token("continue")}, MakeContinueStatement),
|
||||
Rule({Token("goto"), &identifier,
|
||||
Rule({Token("goto"), &name,
|
||||
TryOrDefault<std::vector<Expression*>>(&argumentList)},
|
||||
MakeGotoStatement),
|
||||
Rule({OneOf({"debug", "unreachable"})}, MakeDebugStatement)};
|
||||
|
@ -139,6 +139,65 @@ TEST(LanguageServer, GotoDefinitionClassSuperType) {
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 11}}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionInSignatureGotoStmt) {
|
||||
const std::string source =
|
||||
"type void;\n"
|
||||
"type never;\n"
|
||||
"macro Foo(): never labels Fail {\n"
|
||||
" goto Fail;\n"
|
||||
"}\n";
|
||||
|
||||
TestCompiler compiler;
|
||||
compiler.Compile(source);
|
||||
|
||||
// Find the definition for 'Fail' of the goto statement on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("<torque>");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 7});
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 26}, {2, 30}}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionInTryBlockGoto) {
|
||||
const std::string source =
|
||||
"type void;\n"
|
||||
"type never;\n"
|
||||
"macro Bar() {\n"
|
||||
" try { goto Bailout; }\n"
|
||||
" label Bailout {}\n"
|
||||
"}\n";
|
||||
|
||||
TestCompiler compiler;
|
||||
compiler.Compile(source);
|
||||
|
||||
// Find the definition for 'Bailout' of the goto statement on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("<torque>");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 13});
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {4, 8}, {4, 15}}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionGotoInOtherwise) {
|
||||
const std::string source =
|
||||
"type void;\n"
|
||||
"type never;\n"
|
||||
"macro Foo(): never labels Fail {\n"
|
||||
" goto Fail;\n"
|
||||
"}\n"
|
||||
"macro Bar() {\n"
|
||||
" try { Foo() otherwise goto Bailout; }\n"
|
||||
" label Bailout {}\n"
|
||||
"}\n";
|
||||
|
||||
TestCompiler compiler;
|
||||
compiler.Compile(source);
|
||||
|
||||
// Find the definition for 'Bailout' of the otherwise clause on line 6.
|
||||
const SourceId id = SourceFileMap::GetSourceId("<torque>");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {6, 30});
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
Loading…
Reference in New Issue
Block a user