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 { ...@@ -360,12 +360,10 @@ struct ElementAccessExpression : LocationExpression {
struct FieldAccessExpression : LocationExpression { struct FieldAccessExpression : LocationExpression {
DEFINE_AST_NODE_LEAF_BOILERPLATE(FieldAccessExpression) DEFINE_AST_NODE_LEAF_BOILERPLATE(FieldAccessExpression)
FieldAccessExpression(SourcePosition pos, Expression* object, FieldAccessExpression(SourcePosition pos, Expression* object,
std::string field) Identifier* field)
: LocationExpression(kKind, pos), : LocationExpression(kKind, pos), object(object), field(field) {}
object(object),
field(std::move(field)) {}
Expression* object; Expression* object;
std::string field; Identifier* field;
}; };
struct AssignmentExpression : Expression { struct AssignmentExpression : Expression {
......
...@@ -462,7 +462,7 @@ void DeclarationVisitor::FinalizeStructFieldsAndMethods( ...@@ -462,7 +462,7 @@ void DeclarationVisitor::FinalizeStructFieldsAndMethods(
size_t offset = 0; size_t offset = 0;
for (auto& field : struct_declaration->fields) { for (auto& field : struct_declaration->fields) {
const Type* field_type = Declarations::GetType(field.name_and_type.type); 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, struct_type,
base::nullopt, base::nullopt,
{field.name_and_type.name->value, field_type}, {field.name_and_type.name->value, field_type},
...@@ -502,7 +502,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods( ...@@ -502,7 +502,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
const Field* index_field = const Field* index_field =
&(class_type->LookupField(*field_expression.index)); &(class_type->LookupField(*field_expression.index));
class_type->RegisterField( class_type->RegisterField(
{field_expression.name_and_type.type->pos, {field_expression.name_and_type.name->pos,
class_type, class_type,
index_field, index_field,
{field_expression.name_and_type.name->value, field_type}, {field_expression.name_and_type.name->value, field_type},
...@@ -516,7 +516,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods( ...@@ -516,7 +516,7 @@ void DeclarationVisitor::FinalizeClassFieldsAndMethods(
"declaration"); "declaration");
} }
const Field& field = class_type->RegisterField( const Field& field = class_type->RegisterField(
{field_expression.name_and_type.type->pos, {field_expression.name_and_type.name->pos,
class_type, class_type,
base::nullopt, base::nullopt,
{field_expression.name_and_type.name->value, field_type}, {field_expression.name_and_type.name->value, field_type},
......
...@@ -1728,26 +1728,39 @@ LocationReference ImplementationVisitor::GetLocationReference( ...@@ -1728,26 +1728,39 @@ LocationReference ImplementationVisitor::GetLocationReference(
LocationReference reference = GetLocationReference(expr->object); LocationReference reference = GetLocationReference(expr->object);
if (reference.IsVariableAccess() && if (reference.IsVariableAccess() &&
reference.variable().type()->IsStructType()) { 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( return LocationReference::VariableAccess(
ProjectStructField(reference.variable(), expr->field)); ProjectStructField(reference.variable(), expr->field->value));
} }
if (reference.IsTemporary() && reference.temporary().type()->IsStructType()) { 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( return LocationReference::Temporary(
ProjectStructField(reference.temporary(), expr->field), ProjectStructField(reference.temporary(), expr->field->value),
reference.temporary_description()); reference.temporary_description());
} }
VisitResult object_result = GenerateFetchFromLocation(reference); VisitResult object_result = GenerateFetchFromLocation(reference);
if (const ClassType* class_type = if (const ClassType* class_type =
ClassType::DynamicCast(object_result.type())) { ClassType::DynamicCast(object_result.type())) {
if (class_type->HasField(expr->field)) { if (class_type->HasField(expr->field->value)) {
const Field& field = (class_type->LookupField(expr->field)); 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) { if (field.index) {
return LocationReference::IndexedFieldAccess(object_result, 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( LocationReference ImplementationVisitor::GetLocationReference(
......
...@@ -988,9 +988,8 @@ base::Optional<ParseResult> MakeIdentifierExpression( ...@@ -988,9 +988,8 @@ base::Optional<ParseResult> MakeIdentifierExpression(
base::Optional<ParseResult> MakeFieldAccessExpression( base::Optional<ParseResult> MakeFieldAccessExpression(
ParseResultIterator* child_results) { ParseResultIterator* child_results) {
auto object = child_results->NextAs<Expression*>(); auto object = child_results->NextAs<Expression*>();
auto field = child_results->NextAs<std::string>(); auto field = child_results->NextAs<Identifier*>();
LocationExpression* result = LocationExpression* result = MakeNode<FieldAccessExpression>(object, field);
MakeNode<FieldAccessExpression>(object, std::move(field));
return ParseResult{result}; return ParseResult{result};
} }
...@@ -1366,8 +1365,7 @@ struct TorqueGrammar : Grammar { ...@@ -1366,8 +1365,7 @@ struct TorqueGrammar : Grammar {
// Result: LocationExpression* // Result: LocationExpression*
Symbol locationExpression = { Symbol locationExpression = {
Rule({&identifierExpression}), Rule({&identifierExpression}),
Rule({&primaryExpression, Token("."), &identifier}, Rule({&primaryExpression, Token("."), &name}, MakeFieldAccessExpression),
MakeFieldAccessExpression),
Rule({&primaryExpression, Token("["), expression, Token("]")}, Rule({&primaryExpression, Token("["), expression, Token("]")},
MakeElementAccessExpression)}; 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