[torque-ls] Support "goto-definition" for Types in extends clause

Type declaration may contain a parent type in an "extends" clause.
This CL changes the token type of the name after such a clause
from std::string to Identifier*. The resulting SourcePosition is then
used to implement the "goto-definition" link from that name to the
definition of the parent type.

R=mvstanton@chromium.org

Bug: v8:8880
Change-Id: I9ea6cd83e4d6ef535906e36626f64d458c7d0270
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1511481
Reviewed-by: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: Michael Stanton <mvstanton@chromium.org>
Commit-Queue: Simon Zünd <szuend@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60179}
This commit is contained in:
Simon Zünd 2019-03-08 15:31:37 +01:00 committed by Commit Bot
parent 9d34bb85ba
commit 8e9e151f49
7 changed files with 44 additions and 14 deletions

View File

@ -665,18 +665,18 @@ struct BlockStatement : Statement {
struct TypeDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeDeclaration)
TypeDeclaration(SourcePosition pos, Identifier* name, bool transient,
base::Optional<std::string> extends,
base::Optional<Identifier*> extends,
base::Optional<std::string> generates,
base::Optional<std::string> constexpr_generates)
: Declaration(kKind, pos),
name(name),
transient(transient),
extends(std::move(extends)),
extends(extends),
generates(std::move(generates)),
constexpr_generates(std::move(constexpr_generates)) {}
Identifier* name;
bool transient;
base::Optional<std::string> extends;
base::Optional<Identifier*> extends;
base::Optional<std::string> generates;
base::Optional<std::string> constexpr_generates;
};

View File

@ -348,9 +348,12 @@ void DeclarationVisitor::Visit(TypeDeclaration* decl) {
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + decl->name->value);
constexpr_name->pos = decl->name->pos;
base::Optional<std::string> constexpr_extends;
if (decl->extends)
constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends;
base::Optional<Identifier*> constexpr_extends;
if (decl->extends) {
constexpr_extends =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*decl->extends)->value);
(*constexpr_extends)->pos = (*decl->extends)->pos;
}
Declarations::DeclareAbstractType(constexpr_name, false,
*decl->constexpr_generates, type,
constexpr_extends);

View File

@ -160,11 +160,16 @@ Namespace* Declarations::DeclareNamespace(const std::string& name) {
const AbstractType* Declarations::DeclareAbstractType(
const Identifier* name, bool transient, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent) {
const base::Optional<Identifier*>& parent) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type");
const Type* parent_type = nullptr;
if (parent) {
parent_type = LookupType(QualifiedName{*parent});
auto parent_type_alias = LookupTypeAlias(QualifiedName{(*parent)->value});
parent_type = parent_type_alias->type();
if (GlobalContext::collect_language_server_data()) {
LanguageServerData::AddDefinition(
(*parent)->pos, parent_type_alias->GetDeclarationPosition());
}
}
if (generated == "" && parent) {
generated = parent_type->GetGeneratedTNodeTypeName();

View File

@ -77,7 +77,7 @@ class Declarations {
static const AbstractType* DeclareAbstractType(
const Identifier* name, bool transient, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent = {});
const base::Optional<Identifier*>& parent = {});
static void DeclareType(const Identifier* name, const Type* type,
bool redeclaration);

View File

@ -45,6 +45,7 @@ enum class ParseResultHolderBase::TypeId {
kStdVectorOfString,
kExpressionPtr,
kIdentifierPtr,
kOptionalIdentifierPtr,
kLocationExpressionPtr,
kStatementPtr,
kDeclarationPtr,

View File

@ -64,6 +64,10 @@ template <>
V8_EXPORT_PRIVATE const ParseResultTypeId ParseResultHolder<Identifier*>::id =
ParseResultTypeId::kIdentifierPtr;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<base::Optional<Identifier*>>::id =
ParseResultTypeId::kOptionalIdentifierPtr;
template <>
V8_EXPORT_PRIVATE const ParseResultTypeId
ParseResultHolder<LocationExpression*>::id =
ParseResultTypeId::kLocationExpressionPtr;
@ -521,12 +525,12 @@ base::Optional<ParseResult> MakeTypeDeclaration(
if (!IsValidTypeName(name->value)) {
NamingConventionError("Type", name->value, "UpperCamelCase");
}
auto extends = child_results->NextAs<base::Optional<std::string>>();
auto extends = child_results->NextAs<base::Optional<Identifier*>>();
auto generates = child_results->NextAs<base::Optional<std::string>>();
auto constexpr_generates =
child_results->NextAs<base::Optional<std::string>>();
Declaration* result = MakeNode<TypeDeclaration>(
name, transient, std::move(extends), std::move(generates),
Declaration* result =
MakeNode<TypeDeclaration>(name, transient, extends, std::move(generates),
std::move(constexpr_generates));
return ParseResult{result};
}
@ -1604,7 +1608,7 @@ struct TorqueGrammar : Grammar {
List<StructFieldExpression>(&structField), Token("}")},
MakeStructDeclaration),
Rule({CheckIf(Token("transient")), Token("type"), &name,
Optional<std::string>(Sequence({Token("extends"), &identifier})),
Optional<Identifier*>(Sequence({Token("extends"), &name})),
Optional<std::string>(
Sequence({Token("generates"), &externalString})),
Optional<std::string>(

View File

@ -52,6 +52,23 @@ TEST(LanguageServer, GotoTypeDefinition) {
EXPECT_EQ(*maybe_position, (SourcePosition{id, {3, 5}, {3, 7}}));
}
TEST(LanguageServer, GotoTypeDefinitionExtends) {
const std::string source =
"type void;\n"
"type never;\n"
"type T1 generates 'TNode<T1>';\n"
"type T2 extends T1 generates 'TNode<T2>';";
TestCompiler compiler;
compiler.Compile(source);
// Find the definition for 'T1' of the extends clause on line 3.
const SourceId id = SourceFileMap::GetSourceId("<torque>");
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 16});
ASSERT_TRUE(maybe_position.has_value());
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 7}}));
}
} // namespace torque
} // namespace internal
} // namespace v8