Commit 7d17fd46 authored by Simon Zünd's avatar Simon Zünd Committed by Commit Bot

[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: 's avatarSigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61229}
parent b452a9ec
...@@ -569,12 +569,10 @@ struct ContinueStatement : Statement { ...@@ -569,12 +569,10 @@ struct ContinueStatement : Statement {
struct GotoStatement : Statement { struct GotoStatement : Statement {
DEFINE_AST_NODE_LEAF_BOILERPLATE(GotoStatement) DEFINE_AST_NODE_LEAF_BOILERPLATE(GotoStatement)
GotoStatement(SourcePosition pos, std::string label, GotoStatement(SourcePosition pos, Identifier* label,
const std::vector<Expression*>& arguments) const std::vector<Expression*>& arguments)
: Statement(kKind, pos), : Statement(kKind, pos), label(label), arguments(std::move(arguments)) {}
label(std::move(label)), Identifier* label;
arguments(std::move(arguments)) {}
std::string label;
std::vector<Expression*> arguments; std::vector<Expression*> arguments;
}; };
......
...@@ -811,13 +811,18 @@ VisitResult ImplementationVisitor::Visit(LocationExpression* expr) { ...@@ -811,13 +811,18 @@ VisitResult ImplementationVisitor::Visit(LocationExpression* expr) {
} }
const Type* ImplementationVisitor::Visit(GotoStatement* stmt) { 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(); size_t parameter_count = label->parameter_types.size();
if (stmt->arguments.size() != parameter_count) { if (stmt->arguments.size() != parameter_count) {
ReportError("goto to label has incorrect number of parameters (expected ", ReportError("goto to label has incorrect number of parameters (expected ",
parameter_count, " found ", stmt->arguments.size(), ")"); parameter_count, " found ", stmt->arguments.size(), ")");
} }
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(stmt->label->pos,
label->declaration_position());
}
size_t i = 0; size_t i = 0;
StackRange arguments = assembler().TopRange(0); StackRange arguments = assembler().TopRange(0);
for (Expression* e : stmt->arguments) { for (Expression* e : stmt->arguments) {
......
...@@ -890,10 +890,9 @@ base::Optional<ParseResult> MakeContinueStatement( ...@@ -890,10 +890,9 @@ base::Optional<ParseResult> MakeContinueStatement(
base::Optional<ParseResult> MakeGotoStatement( base::Optional<ParseResult> MakeGotoStatement(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto label = child_results->NextAs<std::string>(); auto label = child_results->NextAs<Identifier*>();
auto arguments = child_results->NextAs<std::vector<Expression*>>(); auto arguments = child_results->NextAs<std::vector<Expression*>>();
Statement* result = Statement* result = MakeNode<GotoStatement>(label, std::move(arguments));
MakeNode<GotoStatement>(std::move(label), std::move(arguments));
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1582,7 +1581,7 @@ struct TorqueGrammar : Grammar { ...@@ -1582,7 +1581,7 @@ struct TorqueGrammar : Grammar {
Rule({Token("tail"), &callExpression}, MakeTailCallStatement), Rule({Token("tail"), &callExpression}, MakeTailCallStatement),
Rule({Token("break")}, MakeBreakStatement), Rule({Token("break")}, MakeBreakStatement),
Rule({Token("continue")}, MakeContinueStatement), Rule({Token("continue")}, MakeContinueStatement),
Rule({Token("goto"), &identifier, Rule({Token("goto"), &name,
TryOrDefault<std::vector<Expression*>>(&argumentList)}, TryOrDefault<std::vector<Expression*>>(&argumentList)},
MakeGotoStatement), MakeGotoStatement),
Rule({OneOf({"debug", "unreachable"})}, MakeDebugStatement)}; Rule({OneOf({"debug", "unreachable"})}, MakeDebugStatement)};
......
...@@ -139,6 +139,65 @@ TEST(LanguageServer, GotoDefinitionClassSuperType) { ...@@ -139,6 +139,65 @@ TEST(LanguageServer, GotoDefinitionClassSuperType) {
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 11}})); 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 torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
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