[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 { struct TypeDeclaration : Declaration {
DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeDeclaration) DEFINE_AST_NODE_LEAF_BOILERPLATE(TypeDeclaration)
TypeDeclaration(SourcePosition pos, Identifier* name, bool transient, 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> generates,
base::Optional<std::string> constexpr_generates) base::Optional<std::string> constexpr_generates)
: Declaration(kKind, pos), : Declaration(kKind, pos),
name(name), name(name),
transient(transient), transient(transient),
extends(std::move(extends)), extends(extends),
generates(std::move(generates)), generates(std::move(generates)),
constexpr_generates(std::move(constexpr_generates)) {} constexpr_generates(std::move(constexpr_generates)) {}
Identifier* name; Identifier* name;
bool transient; bool transient;
base::Optional<std::string> extends; base::Optional<Identifier*> extends;
base::Optional<std::string> generates; base::Optional<std::string> generates;
base::Optional<std::string> constexpr_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); MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + decl->name->value);
constexpr_name->pos = decl->name->pos; constexpr_name->pos = decl->name->pos;
base::Optional<std::string> constexpr_extends; base::Optional<Identifier*> constexpr_extends;
if (decl->extends) if (decl->extends) {
constexpr_extends = CONSTEXPR_TYPE_PREFIX + *decl->extends; constexpr_extends =
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + (*decl->extends)->value);
(*constexpr_extends)->pos = (*decl->extends)->pos;
}
Declarations::DeclareAbstractType(constexpr_name, false, Declarations::DeclareAbstractType(constexpr_name, false,
*decl->constexpr_generates, type, *decl->constexpr_generates, type,
constexpr_extends); constexpr_extends);

View File

@ -160,11 +160,16 @@ Namespace* Declarations::DeclareNamespace(const std::string& name) {
const AbstractType* Declarations::DeclareAbstractType( const AbstractType* Declarations::DeclareAbstractType(
const Identifier* name, bool transient, std::string generated, const Identifier* name, bool transient, std::string generated,
base::Optional<const AbstractType*> non_constexpr_version, base::Optional<const AbstractType*> non_constexpr_version,
const base::Optional<std::string>& parent) { const base::Optional<Identifier*>& parent) {
CheckAlreadyDeclared<TypeAlias>(name->value, "type"); CheckAlreadyDeclared<TypeAlias>(name->value, "type");
const Type* parent_type = nullptr; const Type* parent_type = nullptr;
if (parent) { 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) { if (generated == "" && parent) {
generated = parent_type->GetGeneratedTNodeTypeName(); generated = parent_type->GetGeneratedTNodeTypeName();

View File

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

View File

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

View File

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

View File

@ -52,6 +52,23 @@ TEST(LanguageServer, GotoTypeDefinition) {
EXPECT_EQ(*maybe_position, (SourcePosition{id, {3, 5}, {3, 7}})); 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 torque
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8