[torque-ls] Add basic "goto definition" support for labels
This CL adds navigation support for labels listed in the "otherwise" part of a call expression. There are two places where a definition for such a label can be found: - The signature of the current macro (caller) - A label block of a "try" statement that surrounds the call expression. R=tebbi@chromium.org Bug: v8:8880 Change-Id: If8849ad29abcf94f301d7a51e3e52c5517601bc0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1593295 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#61228}
This commit is contained in:
parent
28df7e8036
commit
b452a9ec99
@ -241,7 +241,7 @@ struct CallMethodExpression : Expression {
|
||||
CallMethodExpression(SourcePosition pos, Expression* target,
|
||||
IdentifierExpression* method,
|
||||
std::vector<Expression*> arguments,
|
||||
std::vector<std::string> labels)
|
||||
std::vector<Identifier*> labels)
|
||||
: Expression(kKind, pos),
|
||||
target(target),
|
||||
method(method),
|
||||
@ -250,21 +250,21 @@ struct CallMethodExpression : Expression {
|
||||
Expression* target;
|
||||
IdentifierExpression* method;
|
||||
std::vector<Expression*> arguments;
|
||||
std::vector<std::string> labels;
|
||||
std::vector<Identifier*> labels;
|
||||
};
|
||||
|
||||
struct CallExpression : Expression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(CallExpression)
|
||||
CallExpression(SourcePosition pos, IdentifierExpression* callee,
|
||||
std::vector<Expression*> arguments,
|
||||
std::vector<std::string> labels)
|
||||
std::vector<Identifier*> labels)
|
||||
: Expression(kKind, pos),
|
||||
callee(callee),
|
||||
arguments(std::move(arguments)),
|
||||
labels(std::move(labels)) {}
|
||||
IdentifierExpression* callee;
|
||||
std::vector<Expression*> arguments;
|
||||
std::vector<std::string> labels;
|
||||
std::vector<Identifier*> labels;
|
||||
};
|
||||
|
||||
struct NameAndExpression {
|
||||
@ -624,13 +624,13 @@ struct ForOfLoopStatement : Statement {
|
||||
|
||||
struct LabelBlock : AstNode {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(LabelBlock)
|
||||
LabelBlock(SourcePosition pos, std::string label,
|
||||
LabelBlock(SourcePosition pos, Identifier* label,
|
||||
const ParameterList& parameters, Statement* body)
|
||||
: AstNode(kKind, pos),
|
||||
label(std::move(label)),
|
||||
label(label),
|
||||
parameters(parameters),
|
||||
body(std::move(body)) {}
|
||||
std::string label;
|
||||
Identifier* label;
|
||||
ParameterList parameters;
|
||||
Statement* body;
|
||||
};
|
||||
@ -712,7 +712,7 @@ struct ClassFieldExpression {
|
||||
};
|
||||
|
||||
struct LabelAndTypes {
|
||||
std::string name;
|
||||
Identifier* name;
|
||||
std::vector<TypeExpression*> types;
|
||||
};
|
||||
|
||||
|
@ -408,11 +408,11 @@ void ImplementationVisitor::VisitMacroCommon(Macro* macro) {
|
||||
std::vector<std::string> label_parameter_variables;
|
||||
for (size_t i = 0; i < label_info.types.size(); ++i) {
|
||||
LowerLabelParameter(label_info.types[i],
|
||||
ExternalLabelParameterName(label_info.name, i),
|
||||
ExternalLabelParameterName(label_info.name->value, i),
|
||||
&label_parameter_variables);
|
||||
}
|
||||
assembler().Emit(GotoExternalInstruction{ExternalLabelName(label_info.name),
|
||||
label_parameter_variables});
|
||||
assembler().Emit(GotoExternalInstruction{
|
||||
ExternalLabelName(label_info.name->value), label_parameter_variables});
|
||||
}
|
||||
|
||||
if (return_type != TypeOracle::GetNeverType()) {
|
||||
@ -1621,7 +1621,8 @@ void ImplementationVisitor::GenerateFunctionDeclaration(
|
||||
if (!first) {
|
||||
o << ", ";
|
||||
}
|
||||
o << "compiler::CodeAssemblerLabel* " << ExternalLabelName(label_info.name);
|
||||
o << "compiler::CodeAssemblerLabel* "
|
||||
<< ExternalLabelName(label_info.name->value);
|
||||
size_t i = 0;
|
||||
for (const Type* type : label_info.types) {
|
||||
std::string generated_type_name;
|
||||
@ -1634,7 +1635,7 @@ void ImplementationVisitor::GenerateFunctionDeclaration(
|
||||
}
|
||||
o << ", ";
|
||||
o << generated_type_name << " "
|
||||
<< ExternalLabelParameterName(label_info.name, i);
|
||||
<< ExternalLabelParameterName(label_info.name->value, i);
|
||||
++i;
|
||||
}
|
||||
}
|
||||
@ -2553,11 +2554,20 @@ StackRange ImplementationVisitor::GenerateLabelGoto(
|
||||
}
|
||||
|
||||
std::vector<Binding<LocalLabel>*> ImplementationVisitor::LabelsFromIdentifiers(
|
||||
const std::vector<std::string>& names) {
|
||||
const std::vector<Identifier*>& names) {
|
||||
std::vector<Binding<LocalLabel>*> result;
|
||||
result.reserve(names.size());
|
||||
for (const auto& name : names) {
|
||||
result.push_back(LookupLabel(name));
|
||||
Binding<LocalLabel>* label = LookupLabel(name->value);
|
||||
result.push_back(label);
|
||||
|
||||
// Link up labels in "otherwise" part of the call expression with
|
||||
// either the label in the signature of the calling macro or the label
|
||||
// block ofa surrounding "try".
|
||||
if (GlobalContext::collect_language_server_data()) {
|
||||
LanguageServerData::AddDefinition(name->pos,
|
||||
label->declaration_position());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ class ImplementationVisitor : public FileVisitor {
|
||||
base::Optional<StackRange> arguments = {});
|
||||
|
||||
std::vector<Binding<LocalLabel>*> LabelsFromIdentifiers(
|
||||
const std::vector<std::string>& names);
|
||||
const std::vector<Identifier*>& names);
|
||||
|
||||
StackRange LowerParameter(const Type* type, const std::string& parameter_name,
|
||||
Stack<std::string>* lowered_parameters);
|
||||
|
@ -208,7 +208,7 @@ Expression* MakeCall(IdentifierExpression* callee,
|
||||
base::Optional<Expression*> target,
|
||||
std::vector<Expression*> arguments,
|
||||
const std::vector<Statement*>& otherwise) {
|
||||
std::vector<std::string> labels;
|
||||
std::vector<Identifier*> labels;
|
||||
|
||||
// All IdentifierExpressions are treated as label names and can be directly
|
||||
// used as labels identifiers. All other statements in a call's otherwise
|
||||
@ -221,14 +221,16 @@ Expression* MakeCall(IdentifierExpression* callee,
|
||||
if (id->generic_arguments.size() != 0) {
|
||||
ReportError("An otherwise label cannot have generic parameters");
|
||||
}
|
||||
labels.push_back(id->name->value);
|
||||
labels.push_back(id->name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
auto label_name = std::string("_label") + std::to_string(label_id++);
|
||||
labels.push_back(label_name);
|
||||
auto label_id = MakeNode<Identifier>(label_name);
|
||||
label_id->pos = SourcePosition::Invalid();
|
||||
labels.push_back(label_id);
|
||||
auto* label_block =
|
||||
MakeNode<LabelBlock>(label_name, ParameterList::Empty(), statement);
|
||||
MakeNode<LabelBlock>(label_id, ParameterList::Empty(), statement);
|
||||
temp_labels.push_back(label_block);
|
||||
}
|
||||
|
||||
@ -809,8 +811,8 @@ base::Optional<ParseResult> MakeTypeswitchStatement(
|
||||
current_block->statements.push_back(
|
||||
MakeNode<ExpressionStatement>(MakeNode<TryLabelExpression>(
|
||||
false, MakeNode<StatementExpression>(case_block),
|
||||
MakeNode<LabelBlock>("_NextCase", ParameterList::Empty(),
|
||||
next_block))));
|
||||
MakeNode<LabelBlock>(MakeNode<Identifier>("_NextCase"),
|
||||
ParameterList::Empty(), next_block))));
|
||||
current_block = next_block;
|
||||
}
|
||||
accumulated_types =
|
||||
@ -952,14 +954,13 @@ base::Optional<ParseResult> MakeForLoopStatement(
|
||||
}
|
||||
|
||||
base::Optional<ParseResult> MakeLabelBlock(ParseResultIterator* child_results) {
|
||||
auto label = child_results->NextAs<std::string>();
|
||||
if (!IsUpperCamelCase(label)) {
|
||||
NamingConventionError("Label", label, "UpperCamelCase");
|
||||
auto label = child_results->NextAs<Identifier*>();
|
||||
if (!IsUpperCamelCase(label->value)) {
|
||||
NamingConventionError("Label", label->value, "UpperCamelCase");
|
||||
}
|
||||
auto parameters = child_results->NextAs<ParameterList>();
|
||||
auto body = child_results->NextAs<Statement*>();
|
||||
LabelBlock* result =
|
||||
MakeNode<LabelBlock>(std::move(label), std::move(parameters), body);
|
||||
LabelBlock* result = MakeNode<LabelBlock>(label, std::move(parameters), body);
|
||||
return ParseResult{result};
|
||||
}
|
||||
|
||||
@ -974,8 +975,8 @@ base::Optional<ParseResult> MakeCatchBlock(ParseResultIterator* child_results) {
|
||||
parameters.types.push_back(MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, false, "Object"));
|
||||
parameters.has_varargs = false;
|
||||
LabelBlock* result =
|
||||
MakeNode<LabelBlock>("_catch", std::move(parameters), body);
|
||||
LabelBlock* result = MakeNode<LabelBlock>(MakeNode<Identifier>("_catch"),
|
||||
std::move(parameters), body);
|
||||
return ParseResult{result};
|
||||
}
|
||||
|
||||
@ -1114,12 +1115,12 @@ base::Optional<ParseResult> MakeConditionalExpression(
|
||||
|
||||
base::Optional<ParseResult> MakeLabelAndTypes(
|
||||
ParseResultIterator* child_results) {
|
||||
auto name = child_results->NextAs<std::string>();
|
||||
if (!IsUpperCamelCase(name)) {
|
||||
NamingConventionError("Label", name, "UpperCamelCase");
|
||||
auto name = child_results->NextAs<Identifier*>();
|
||||
if (!IsUpperCamelCase(name->value)) {
|
||||
NamingConventionError("Label", name->value, "UpperCamelCase");
|
||||
}
|
||||
auto types = child_results->NextAs<std::vector<TypeExpression*>>();
|
||||
return ParseResult{LabelAndTypes{std::move(name), std::move(types)}};
|
||||
return ParseResult{LabelAndTypes{name, std::move(types)}};
|
||||
}
|
||||
|
||||
base::Optional<ParseResult> MakeNameAndType(
|
||||
@ -1335,7 +1336,7 @@ struct TorqueGrammar : Grammar {
|
||||
|
||||
// Result: LabelAndTypes
|
||||
Symbol labelParameter = {Rule(
|
||||
{&identifier,
|
||||
{&name,
|
||||
TryOrDefault<TypeList>(Sequence({Token("("), typeList, Token(")")}))},
|
||||
MakeLabelAndTypes)};
|
||||
|
||||
@ -1542,7 +1543,7 @@ struct TorqueGrammar : Grammar {
|
||||
|
||||
// Result: LabelBlock*
|
||||
Symbol labelBlock = {
|
||||
Rule({Token("label"), &identifier,
|
||||
Rule({Token("label"), &name,
|
||||
TryOrDefault<ParameterList>(¶meterListNoVararg), &block},
|
||||
MakeLabelBlock)};
|
||||
|
||||
|
@ -595,7 +595,7 @@ struct LabelDefinition {
|
||||
typedef std::vector<LabelDefinition> LabelDefinitionVector;
|
||||
|
||||
struct LabelDeclaration {
|
||||
std::string name;
|
||||
Identifier* name;
|
||||
TypeVector types;
|
||||
};
|
||||
|
||||
|
@ -79,6 +79,49 @@ TEST(LanguageServer, GotoTypeDefinitionNoDataForFile) {
|
||||
EXPECT_FALSE(LanguageServerData::FindDefinition(test_id, {0, 0}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionInSignature) {
|
||||
const std::string source =
|
||||
"type void;\n"
|
||||
"type never;\n"
|
||||
"macro Foo(): never labels Fail {\n"
|
||||
" goto Fail;\n"
|
||||
"}\n"
|
||||
"macro Bar() labels Bailout {\n"
|
||||
" Foo() otherwise 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, 18});
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {5, 19}, {5, 26}}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionInTryBlock) {
|
||||
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 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, 25});
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoDefinitionClassSuperType) {
|
||||
const std::string source =
|
||||
"type void;\n"
|
||||
|
Loading…
Reference in New Issue
Block a user