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

[torque-ls] Add "goto definition" support for class and struct fields

This CL changes the FieldAccessExpression to include a SourcePosition
for the field, allowing a jump from such an access to the definition
of a field inside a class or struct.

Drive-by: Change the source position of a field from the position
of its type to the position of its name. This will coincidentally
improve the accuracy of error messages.

R=danno@chromium.org

Bug: v8:8880
Change-Id: I7996e8a57a2ff90e8bdca6f40c1b298d48071e23
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1512573Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60162}
parent 0f82719b
......@@ -360,12 +360,10 @@ struct ElementAccessExpression : LocationExpression {
struct FieldAccessExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(FieldAccessExpression)
FieldAccessExpression(SourcePosition pos, Expression* object,
std::string field)
: LocationExpression(kKind, pos),
object(object),
field(std::move(field)) {}
Identifier* field)
: LocationExpression(kKind, pos), object(object), field(field) {}
Expression* object;
std::string field;
Identifier* field;
};
struct AssignmentExpression : Expression {
......
......@@ -462,7 +462,7 @@ void DeclarationVisitor::FinalizeStructFieldsAndMethods(
size_t offset = 0;
for (auto& field : struct_declaration->fields) {
const Type* field_type = Declarations::GetType(field.name_and_type.type);
struct_type->RegisterField({field.name_and_type.type->pos,
struct_type->RegisterField({field.name_and_type.name->pos,
struct_type,
base::nullopt,
{field.name_and_type.name->value, field_type},
......@@ -502,7 +502,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
const Field* index_field =
&(class_type->LookupField(*field_expression.index));
class_type->RegisterField(
{field_expression.name_and_type.type->pos,
{field_expression.name_and_type.name->pos,
class_type,
index_field,
{field_expression.name_and_type.name->value, field_type},
......@@ -516,7 +516,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
"declaration");
}
const Field& field = class_type->RegisterField(
{field_expression.name_and_type.type->pos,
{field_expression.name_and_type.name->pos,
class_type,
base::nullopt,
{field_expression.name_and_type.name->value, field_type},
......
......@@ -1728,26 +1728,39 @@ LocationReference ImplementationVisitor::GetLocationReference(
LocationReference reference = GetLocationReference(expr->object);
if (reference.IsVariableAccess() &&
reference.variable().type()->IsStructType()) {
if (GlobalContext::collect_language_server_data()) {
const StructType* type = StructType::cast(reference.variable().type());
const Field& field = type->LookupField(expr->field->value);
LanguageServerData::AddDefinition(expr->field->pos, field.pos);
}
return LocationReference::VariableAccess(
ProjectStructField(reference.variable(), expr->field));
ProjectStructField(reference.variable(), expr->field->value));
}
if (reference.IsTemporary() && reference.temporary().type()->IsStructType()) {
if (GlobalContext::collect_language_server_data()) {
const StructType* type = StructType::cast(reference.temporary().type());
const Field& field = type->LookupField(expr->field->value);
LanguageServerData::AddDefinition(expr->field->pos, field.pos);
}
return LocationReference::Temporary(
ProjectStructField(reference.temporary(), expr->field),
ProjectStructField(reference.temporary(), expr->field->value),
reference.temporary_description());
}
VisitResult object_result = GenerateFetchFromLocation(reference);
if (const ClassType* class_type =
ClassType::DynamicCast(object_result.type())) {
if (class_type->HasField(expr->field)) {
const Field& field = (class_type->LookupField(expr->field));
if (class_type->HasField(expr->field->value)) {
const Field& field = (class_type->LookupField(expr->field->value));
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(expr->field->pos, field.pos);
}
if (field.index) {
return LocationReference::IndexedFieldAccess(object_result,
expr->field);
expr->field->value);
}
}
}
return LocationReference::FieldAccess(object_result, expr->field);
return LocationReference::FieldAccess(object_result, expr->field->value);
}
LocationReference ImplementationVisitor::GetLocationReference(
......
......@@ -988,9 +988,8 @@ base::Optional<ParseResult> MakeIdentifierExpression(
base::Optional<ParseResult> MakeFieldAccessExpression(
ParseResultIterator* child_results) {
auto object = child_results->NextAs<Expression*>();
auto field = child_results->NextAs<std::string>();
LocationExpression* result =
MakeNode<FieldAccessExpression>(object, std::move(field));
auto field = child_results->NextAs<Identifier*>();
LocationExpression* result = MakeNode<FieldAccessExpression>(object, field);
return ParseResult{result};
}
......@@ -1366,8 +1365,7 @@ struct TorqueGrammar : Grammar {
// Result: LocationExpression*
Symbol locationExpression = {
Rule({&identifierExpression}),
Rule({&primaryExpression, Token("."), &identifier},
MakeFieldAccessExpression),
Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression),
Rule({&primaryExpression, Token("["), expression, Token("]")},
MakeElementAccessExpression)};
......
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