[torque-ls] List macros and builtins as document symbols
This CL adds support for macros, builtins, generics and specializations for the "textDocument/symbol" request. To filter out implicitly created specializations, the "is_user_defined" flag is hoisted from Macro to the Declarable super class. As a side-effect, errors thrown during specialization now have the correct SourcePosition. Drive-by-change: Using "Goto Definition" on the identifier of the specialization will jump to the associated generic. Bug: v8:8880 Change-Id: I0c60571c58107375c1b5d2a8e620cf12a0f0f3fc Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1609795 Commit-Queue: Simon Zünd <szuend@chromium.org> Reviewed-by: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Tobias Tebbi <tebbi@chromium.org> Cr-Commit-Position: refs/heads/master@{#61486}
This commit is contained in:
parent
f0234f75af
commit
a41aaf78e1
@ -878,19 +878,19 @@ struct GenericDeclaration : Declaration {
|
||||
|
||||
struct SpecializationDeclaration : Declaration {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(SpecializationDeclaration)
|
||||
SpecializationDeclaration(SourcePosition pos, std::string name,
|
||||
SpecializationDeclaration(SourcePosition pos, Identifier* name,
|
||||
std::vector<TypeExpression*> generic_parameters,
|
||||
ParameterList parameters,
|
||||
TypeExpression* return_type,
|
||||
LabelAndTypesVector labels, Statement* b)
|
||||
: Declaration(kKind, pos),
|
||||
name(std::move(name)),
|
||||
name(name),
|
||||
external(false),
|
||||
generic_parameters(std::move(generic_parameters)),
|
||||
signature(new CallableNodeSignature{std::move(parameters), return_type,
|
||||
std::move(labels)}),
|
||||
body(b) {}
|
||||
std::string name;
|
||||
Identifier* name;
|
||||
bool external;
|
||||
std::vector<TypeExpression*> generic_parameters;
|
||||
std::unique_ptr<CallableNodeSignature> signature;
|
||||
|
@ -90,6 +90,11 @@ class Declarable {
|
||||
identifier_position_ = position;
|
||||
}
|
||||
|
||||
bool IsUserDefined() const { return is_user_defined_; }
|
||||
void SetIsUserDefined(bool is_user_defined) {
|
||||
is_user_defined_ = is_user_defined;
|
||||
}
|
||||
|
||||
protected:
|
||||
explicit Declarable(Kind kind) : kind_(kind) {}
|
||||
|
||||
@ -98,6 +103,7 @@ class Declarable {
|
||||
Scope* const parent_scope_ = CurrentScope::Get();
|
||||
SourcePosition position_ = CurrentSourcePosition::Get();
|
||||
SourcePosition identifier_position_ = SourcePosition::Invalid();
|
||||
bool is_user_defined_ = true;
|
||||
};
|
||||
|
||||
#define DECLARE_DECLARABLE_BOILERPLATE(x, y) \
|
||||
@ -312,8 +318,6 @@ class Macro : public Callable {
|
||||
return external_assembler_name_;
|
||||
}
|
||||
|
||||
bool is_user_defined() const { return is_user_defined_; }
|
||||
|
||||
protected:
|
||||
Macro(Declarable::Kind kind, std::string external_name,
|
||||
std::string readable_name, std::string external_assembler_name,
|
||||
@ -321,8 +325,8 @@ class Macro : public Callable {
|
||||
base::Optional<Statement*> body, bool is_user_defined)
|
||||
: Callable(kind, std::move(external_name), std::move(readable_name),
|
||||
signature, transitioning, body),
|
||||
external_assembler_name_(std::move(external_assembler_name)),
|
||||
is_user_defined_(is_user_defined) {
|
||||
external_assembler_name_(std::move(external_assembler_name)) {
|
||||
SetIsUserDefined(is_user_defined);
|
||||
if (signature.parameter_types.var_args) {
|
||||
ReportError("Varargs are not supported for macros.");
|
||||
}
|
||||
@ -339,7 +343,6 @@ class Macro : public Callable {
|
||||
transitioning, body, is_user_defined) {}
|
||||
|
||||
std::string external_assembler_name_;
|
||||
bool is_user_defined_;
|
||||
};
|
||||
|
||||
class Method : public Macro {
|
||||
|
@ -210,7 +210,8 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
ReportError(stream.str());
|
||||
}
|
||||
|
||||
std::vector<Generic*> generic_list = Declarations::LookupGeneric(decl->name);
|
||||
std::vector<Generic*> generic_list =
|
||||
Declarations::LookupGeneric(decl->name->value);
|
||||
// Find the matching generic specialization based on the concrete parameter
|
||||
// list.
|
||||
Generic* matching_generic = nullptr;
|
||||
@ -253,10 +254,15 @@ void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
ReportError(stream.str());
|
||||
}
|
||||
|
||||
if (GlobalContext::collect_language_server_data()) {
|
||||
LanguageServerData::AddDefinition(decl->name->pos,
|
||||
matching_generic->IdentifierPosition());
|
||||
}
|
||||
|
||||
Specialize(SpecializationKey{matching_generic, TypeVisitor::ComputeTypeVector(
|
||||
decl->generic_parameters)},
|
||||
matching_generic->declaration()->callable, decl->signature.get(),
|
||||
decl->body);
|
||||
decl->body, decl->pos);
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
|
||||
@ -315,9 +321,10 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
|
||||
key.generic->Position());
|
||||
}
|
||||
CurrentScope::Scope generic_scope(key.generic->ParentScope());
|
||||
Callable* result =
|
||||
Specialize(key, key.generic->declaration()->callable, base::nullopt,
|
||||
key.generic->declaration()->body);
|
||||
Callable* result = Specialize(key, key.generic->declaration()->callable,
|
||||
base::nullopt, key.generic->declaration()->body,
|
||||
CurrentSourcePosition::Get());
|
||||
result->SetIsUserDefined(false);
|
||||
CurrentScope::Scope callable_scope(result);
|
||||
DeclareSpecializedTypes(key);
|
||||
return result;
|
||||
@ -326,10 +333,8 @@ Callable* DeclarationVisitor::SpecializeImplicit(const SpecializationKey& key) {
|
||||
Callable* DeclarationVisitor::Specialize(
|
||||
const SpecializationKey& key, CallableNode* declaration,
|
||||
base::Optional<const CallableNodeSignature*> signature,
|
||||
base::Optional<Statement*> body) {
|
||||
// TODO(tebbi): The error should point to the source position where the
|
||||
// instantiation was requested.
|
||||
CurrentSourcePosition::Scope pos_scope(key.generic->declaration()->pos);
|
||||
base::Optional<Statement*> body, SourcePosition position) {
|
||||
CurrentSourcePosition::Scope pos_scope(position);
|
||||
size_t generic_parameter_count =
|
||||
key.generic->declaration()->generic_parameters.size();
|
||||
if (generic_parameter_count != key.specialized_types.size()) {
|
||||
|
@ -100,7 +100,7 @@ class DeclarationVisitor {
|
||||
static Callable* Specialize(
|
||||
const SpecializationKey& key, CallableNode* declaration,
|
||||
base::Optional<const CallableNodeSignature*> signature,
|
||||
base::Optional<Statement*> body);
|
||||
base::Optional<Statement*> body, SourcePosition position);
|
||||
|
||||
private:
|
||||
static void DeclareSpecializedTypes(const SpecializationKey& key);
|
||||
|
@ -269,15 +269,7 @@ void HandleGotoDefinitionRequest(GotoDefinitionRequest request,
|
||||
|
||||
if (auto maybe_definition = LanguageServerData::FindDefinition(id, pos)) {
|
||||
SourcePosition definition = *maybe_definition;
|
||||
|
||||
std::string definition_file = SourceFileMap::GetSource(definition.source);
|
||||
response.result().set_uri(definition_file);
|
||||
|
||||
Range range = response.result().range();
|
||||
range.start().set_line(definition.start.line);
|
||||
range.start().set_character(definition.start.column);
|
||||
range.end().set_line(definition.end.line);
|
||||
range.end().set_character(definition.end.column);
|
||||
response.result().SetTo(definition);
|
||||
} else {
|
||||
response.SetNull("result");
|
||||
}
|
||||
@ -297,8 +289,31 @@ void HandleDocumentSymbolRequest(DocumentSymbolRequest request,
|
||||
DocumentSymbolResponse response;
|
||||
response.set_id(request.id());
|
||||
|
||||
// TODO(szuend): Convert declarables and other symbols into SymbolInformation
|
||||
// objects here.
|
||||
SourceId id =
|
||||
SourceFileMap::GetSourceId(request.params().textDocument().uri());
|
||||
|
||||
for (const auto& symbol : LanguageServerData::SymbolsForSourceId(id)) {
|
||||
DCHECK(symbol->IsUserDefined());
|
||||
if (symbol->IsMacro()) {
|
||||
Macro* macro = Macro::cast(symbol);
|
||||
SymbolInformation symbol = response.add_result();
|
||||
symbol.set_name(macro->ReadableName());
|
||||
symbol.set_kind(SymbolKind::kFunction);
|
||||
symbol.location().SetTo(macro->Position());
|
||||
} else if (symbol->IsBuiltin()) {
|
||||
Builtin* builtin = Builtin::cast(symbol);
|
||||
SymbolInformation symbol = response.add_result();
|
||||
symbol.set_name(builtin->ReadableName());
|
||||
symbol.set_kind(SymbolKind::kFunction);
|
||||
symbol.location().SetTo(builtin->Position());
|
||||
} else if (symbol->IsGeneric()) {
|
||||
Generic* generic = Generic::cast(symbol);
|
||||
SymbolInformation symbol = response.add_result();
|
||||
symbol.set_name(generic->name());
|
||||
symbol.set_kind(SymbolKind::kFunction);
|
||||
symbol.location().SetTo(generic->Position());
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger empty array creation in case no symbols were found.
|
||||
USE(response.result_size());
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "src/base/logging.h"
|
||||
#include "src/torque/ls/json.h"
|
||||
#include "src/torque/ls/message-macros.h"
|
||||
#include "src/torque/source-positions.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
@ -238,6 +239,14 @@ class Location : public NestedJsonAccessor {
|
||||
|
||||
JSON_STRING_ACCESSORS(uri)
|
||||
JSON_OBJECT_ACCESSORS(Range, range)
|
||||
|
||||
void SetTo(SourcePosition position) {
|
||||
set_uri(SourceFileMap::GetSource(position.source));
|
||||
range().start().set_line(position.start.line);
|
||||
range().start().set_character(position.start.column);
|
||||
range().end().set_line(position.end.line);
|
||||
range().end().set_character(position.end.column);
|
||||
}
|
||||
};
|
||||
|
||||
class TextDocumentIdentifier : public NestedJsonAccessor {
|
||||
|
@ -38,12 +38,9 @@ void LanguageServerData::PrepareAllDeclarableSymbols() {
|
||||
global_context_->declarables_;
|
||||
|
||||
for (const auto& declarable : all_declarables) {
|
||||
// Auto-generated macros to access class fields should not show up in
|
||||
// search results.
|
||||
if (declarable->IsMacro() &&
|
||||
!Macro::cast(declarable.get())->is_user_defined()) {
|
||||
continue;
|
||||
}
|
||||
// Class field accessors and implicit specializations are
|
||||
// auto-generated and should not show up.
|
||||
if (!declarable->IsUserDefined()) continue;
|
||||
|
||||
SourceId source = declarable->Position().source;
|
||||
symbols_map_[source].push_back(declarable.get());
|
||||
|
@ -707,7 +707,7 @@ base::Optional<ParseResult> MakeNamespaceDeclaration(
|
||||
|
||||
base::Optional<ParseResult> MakeSpecializationDeclaration(
|
||||
ParseResultIterator* child_results) {
|
||||
auto name = child_results->NextAs<std::string>();
|
||||
auto name = child_results->NextAs<Identifier*>();
|
||||
auto generic_parameters =
|
||||
child_results->NextAs<std::vector<TypeExpression*>>();
|
||||
auto parameters = child_results->NextAs<ParameterList>();
|
||||
@ -1841,9 +1841,8 @@ struct TorqueGrammar : Grammar {
|
||||
TryOrDefault<GenericParameters>(&genericParameters),
|
||||
¶meterListAllowVararg, &optionalReturnType, &optionalBody},
|
||||
AsSingletonVector<Declaration*, MakeTorqueBuiltinDeclaration>()),
|
||||
Rule({&identifier, &genericSpecializationTypeList,
|
||||
¶meterListAllowVararg, &optionalReturnType, optionalLabelList,
|
||||
&block},
|
||||
Rule({&name, &genericSpecializationTypeList, ¶meterListAllowVararg,
|
||||
&optionalReturnType, optionalLabelList, &block},
|
||||
AsSingletonVector<Declaration*, MakeSpecializationDeclaration>()),
|
||||
Rule({Token("#include"), &externalString},
|
||||
AsSingletonVector<Declaration*, MakeCppIncludeDeclaration>())};
|
||||
|
Loading…
Reference in New Issue
Block a user