[Torque] Add Kythe api to Torque compiler
Prepare the Torque compiler to generate Kythe artifacts to be consumed by CodeSearch. Drive-by changes. * Extend SourcePosition by an offset in the input string, as this is required by the Kythe graph. * Correctly set missing identifier positions in Declarations. Bug: v8:12261 Change-Id: Ida0a4a562c99f58ab924ddde36f3146f3d3fd415 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3181102 Commit-Queue: Nico Hartmann <nicohartmann@chromium.org> Reviewed-by: Seth Brenith <seth.brenith@microsoft.com> Cr-Commit-Position: refs/heads/main@{#77099}
This commit is contained in:
parent
063384f76e
commit
6c9f799207
2
BUILD.gn
2
BUILD.gn
@ -4716,6 +4716,8 @@ v8_source_set("torque_base") {
|
||||
"src/torque/instance-type-generator.cc",
|
||||
"src/torque/instructions.cc",
|
||||
"src/torque/instructions.h",
|
||||
"src/torque/kythe-data.cc",
|
||||
"src/torque/kythe-data.h",
|
||||
"src/torque/parameter-difference.h",
|
||||
"src/torque/server-data.cc",
|
||||
"src/torque/server-data.h",
|
||||
|
@ -625,18 +625,18 @@ struct BasicTypeExpression : TypeExpression {
|
||||
DEFINE_AST_NODE_LEAF_BOILERPLATE(BasicTypeExpression)
|
||||
BasicTypeExpression(SourcePosition pos,
|
||||
std::vector<std::string> namespace_qualification,
|
||||
std::string name,
|
||||
Identifier* name,
|
||||
std::vector<TypeExpression*> generic_arguments)
|
||||
: TypeExpression(kKind, pos),
|
||||
namespace_qualification(std::move(namespace_qualification)),
|
||||
is_constexpr(IsConstexprName(name)),
|
||||
name(std::move(name)),
|
||||
is_constexpr(IsConstexprName(name->value)),
|
||||
name(name),
|
||||
generic_arguments(std::move(generic_arguments)) {}
|
||||
BasicTypeExpression(SourcePosition pos, std::string name)
|
||||
: BasicTypeExpression(pos, {}, std::move(name), {}) {}
|
||||
BasicTypeExpression(SourcePosition pos, Identifier* name)
|
||||
: BasicTypeExpression(pos, {}, name, {}) {}
|
||||
std::vector<std::string> namespace_qualification;
|
||||
bool is_constexpr;
|
||||
std::string name;
|
||||
Identifier* name;
|
||||
std::vector<TypeExpression*> generic_arguments;
|
||||
};
|
||||
|
||||
@ -1306,10 +1306,9 @@ inline VarDeclarationStatement* MakeConstDeclarationStatement(
|
||||
}
|
||||
|
||||
inline BasicTypeExpression* MakeBasicTypeExpression(
|
||||
std::vector<std::string> namespace_qualification, std::string name,
|
||||
std::vector<std::string> namespace_qualification, Identifier* name,
|
||||
std::vector<TypeExpression*> generic_arguments = {}) {
|
||||
return MakeNode<BasicTypeExpression>(std::move(namespace_qualification),
|
||||
std::move(name),
|
||||
return MakeNode<BasicTypeExpression>(std::move(namespace_qualification), name,
|
||||
std::move(generic_arguments));
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "src/torque/declaration-visitor.h"
|
||||
|
||||
#include "src/torque/ast.h"
|
||||
#include "src/torque/kythe-data.h"
|
||||
#include "src/torque/server-data.h"
|
||||
#include "src/torque/type-inference.h"
|
||||
#include "src/torque/type-visitor.h"
|
||||
@ -109,16 +110,20 @@ Builtin* DeclarationVisitor::CreateBuiltin(BuiltinDeclaration* decl,
|
||||
Error("Builtins cannot have return type void.");
|
||||
}
|
||||
|
||||
return Declarations::CreateBuiltin(std::move(external_name),
|
||||
std::move(readable_name), kind,
|
||||
std::move(signature), body);
|
||||
Builtin* builtin = Declarations::CreateBuiltin(std::move(external_name),
|
||||
std::move(readable_name), kind,
|
||||
std::move(signature), body);
|
||||
// TODO(v8:12261): Recheck this.
|
||||
// builtin->SetIdentifierPosition(decl->name->pos);
|
||||
return builtin;
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(ExternalBuiltinDeclaration* decl) {
|
||||
Declarations::Declare(
|
||||
decl->name->value,
|
||||
Builtin* builtin =
|
||||
CreateBuiltin(decl, decl->name->value, decl->name->value,
|
||||
TypeVisitor::MakeSignature(decl), base::nullopt));
|
||||
TypeVisitor::MakeSignature(decl), base::nullopt);
|
||||
builtin->SetIdentifierPosition(decl->name->pos);
|
||||
Declarations::Declare(decl->name->value, builtin);
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) {
|
||||
@ -152,29 +157,43 @@ void DeclarationVisitor::Visit(ExternalRuntimeDeclaration* decl) {
|
||||
}
|
||||
}
|
||||
|
||||
Declarations::DeclareRuntimeFunction(decl->name->value, signature);
|
||||
RuntimeFunction* function =
|
||||
Declarations::DeclareRuntimeFunction(decl->name->value, signature);
|
||||
function->SetIdentifierPosition(decl->name->pos);
|
||||
function->SetPosition(decl->pos);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddFunctionDefinition(function);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(ExternalMacroDeclaration* decl) {
|
||||
Declarations::DeclareMacro(
|
||||
Macro* macro = Declarations::DeclareMacro(
|
||||
decl->name->value, true, decl->external_assembler_name,
|
||||
TypeVisitor::MakeSignature(decl), base::nullopt, decl->op);
|
||||
macro->SetIdentifierPosition(decl->name->pos);
|
||||
macro->SetPosition(decl->pos);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddFunctionDefinition(macro);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(TorqueBuiltinDeclaration* decl) {
|
||||
Declarations::Declare(
|
||||
decl->name->value,
|
||||
CreateBuiltin(decl, decl->name->value, decl->name->value,
|
||||
TypeVisitor::MakeSignature(decl), decl->body));
|
||||
auto builtin = CreateBuiltin(decl, decl->name->value, decl->name->value,
|
||||
TypeVisitor::MakeSignature(decl), decl->body);
|
||||
builtin->SetIdentifierPosition(decl->name->pos);
|
||||
builtin->SetPosition(decl->pos);
|
||||
Declarations::Declare(decl->name->value, builtin);
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(TorqueMacroDeclaration* decl) {
|
||||
Macro* macro = Declarations::DeclareMacro(
|
||||
decl->name->value, decl->export_to_csa, base::nullopt,
|
||||
TypeVisitor::MakeSignature(decl), decl->body, decl->op);
|
||||
// TODO(szuend): Set identifier_position to decl->name->pos once all callable
|
||||
// names are changed from std::string to Identifier*.
|
||||
macro->SetIdentifierPosition(decl->name->pos);
|
||||
macro->SetPosition(decl->pos);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddFunctionDefinition(macro);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(IntrinsicDeclaration* decl) {
|
||||
@ -183,8 +202,11 @@ void DeclarationVisitor::Visit(IntrinsicDeclaration* decl) {
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(ConstDeclaration* decl) {
|
||||
Declarations::DeclareNamespaceConstant(
|
||||
auto constant = Declarations::DeclareNamespaceConstant(
|
||||
decl->name, TypeVisitor::ComputeType(decl->type), decl->expression);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddConstantDefinition(constant);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(SpecializationDeclaration* decl) {
|
||||
@ -260,7 +282,11 @@ void DeclarationVisitor::Visit(ExternConstDeclaration* decl) {
|
||||
ReportError(stream.str());
|
||||
}
|
||||
|
||||
Declarations::DeclareExternConstant(decl->name, type, decl->literal);
|
||||
ExternConstant* constant =
|
||||
Declarations::DeclareExternConstant(decl->name, type, decl->literal);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddConstantDefinition(constant);
|
||||
}
|
||||
}
|
||||
|
||||
void DeclarationVisitor::Visit(CppIncludeDeclaration* decl) {
|
||||
|
@ -277,11 +277,12 @@ RuntimeFunction* Declarations::DeclareRuntimeFunction(
|
||||
new RuntimeFunction(name, signature))));
|
||||
}
|
||||
|
||||
void Declarations::DeclareExternConstant(Identifier* name, const Type* type,
|
||||
std::string value) {
|
||||
ExternConstant* Declarations::DeclareExternConstant(Identifier* name,
|
||||
const Type* type,
|
||||
std::string value) {
|
||||
CheckAlreadyDeclared<Value>(name->value, "constant");
|
||||
Declare(name->value, std::unique_ptr<ExternConstant>(
|
||||
new ExternConstant(name, type, value)));
|
||||
return Declare(name->value, std::unique_ptr<ExternConstant>(
|
||||
new ExternConstant(name, type, value)));
|
||||
}
|
||||
|
||||
NamespaceConstant* Declarations::DeclareNamespaceConstant(Identifier* name,
|
||||
|
@ -132,8 +132,9 @@ class Declarations {
|
||||
static RuntimeFunction* DeclareRuntimeFunction(const std::string& name,
|
||||
const Signature& signature);
|
||||
|
||||
static void DeclareExternConstant(Identifier* name, const Type* type,
|
||||
std::string value);
|
||||
static ExternConstant* DeclareExternConstant(Identifier* name,
|
||||
const Type* type,
|
||||
std::string value);
|
||||
static NamespaceConstant* DeclareNamespaceConstant(Identifier* name,
|
||||
const Type* type,
|
||||
Expression* body);
|
||||
|
@ -18,11 +18,12 @@ namespace torque {
|
||||
namespace {
|
||||
|
||||
struct LineAndColumnTracker {
|
||||
LineAndColumn previous{0, 0};
|
||||
LineAndColumn current{0, 0};
|
||||
LineAndColumn previous{0, 0, 0};
|
||||
LineAndColumn current{0, 0, 0};
|
||||
|
||||
void Advance(InputPosition from, InputPosition to) {
|
||||
previous = current;
|
||||
current.offset += std::distance(from, to);
|
||||
while (from != to) {
|
||||
if (*from == '\n') {
|
||||
current.line += 1;
|
||||
@ -187,7 +188,8 @@ const Item* RunEarleyAlgorithm(
|
||||
// Worklist for items at the next position.
|
||||
std::vector<Item> future_items;
|
||||
CurrentSourcePosition::Scope source_position(
|
||||
SourcePosition{CurrentSourceFile::Get(), {0, 0}, {0, 0}});
|
||||
SourcePosition{CurrentSourceFile::Get(), LineAndColumn::Invalid(),
|
||||
LineAndColumn::Invalid()});
|
||||
std::vector<const Item*> completed_items;
|
||||
std::unordered_map<std::pair<size_t, Symbol*>, std::set<const Item*>,
|
||||
base::hash<std::pair<size_t, Symbol*>>>
|
||||
|
@ -13,12 +13,14 @@ DEFINE_CONTEXTUAL_VARIABLE(TargetArchitecture)
|
||||
|
||||
GlobalContext::GlobalContext(Ast ast)
|
||||
: collect_language_server_data_(false),
|
||||
collect_kythe_data_(false),
|
||||
force_assert_statements_(false),
|
||||
annotate_ir_(false),
|
||||
ast_(std::move(ast)) {
|
||||
CurrentScope::Scope current_scope(nullptr);
|
||||
CurrentSourcePosition::Scope current_source_position(
|
||||
SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}});
|
||||
SourcePosition{CurrentSourceFile::Get(), LineAndColumn::Invalid(),
|
||||
LineAndColumn::Invalid()});
|
||||
default_namespace_ =
|
||||
RegisterDeclarable(std::make_unique<Namespace>(kBaseNamespaceName));
|
||||
}
|
||||
|
@ -49,6 +49,8 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
static bool collect_language_server_data() {
|
||||
return Get().collect_language_server_data_;
|
||||
}
|
||||
static void SetCollectKytheData() { Get().collect_kythe_data_ = true; }
|
||||
static bool collect_kythe_data() { return Get().collect_kythe_data_; }
|
||||
static void SetForceAssertStatements() {
|
||||
Get().force_assert_statements_ = true;
|
||||
}
|
||||
@ -118,6 +120,7 @@ class GlobalContext : public ContextualClass<GlobalContext> {
|
||||
|
||||
private:
|
||||
bool collect_language_server_data_;
|
||||
bool collect_kythe_data_;
|
||||
bool force_assert_statements_;
|
||||
bool annotate_ir_;
|
||||
Namespace* default_namespace_;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "src/torque/csa-generator.h"
|
||||
#include "src/torque/declaration-visitor.h"
|
||||
#include "src/torque/global-context.h"
|
||||
#include "src/torque/kythe-data.h"
|
||||
#include "src/torque/parameter-difference.h"
|
||||
#include "src/torque/server-data.h"
|
||||
#include "src/torque/source-positions.h"
|
||||
@ -29,6 +30,8 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace torque {
|
||||
|
||||
uint64_t next_unique_binding_index = 0;
|
||||
|
||||
// Sadly, 'using std::string_literals::operator""s;' is bugged in MSVC (see
|
||||
// https://developercommunity.visualstudio.com/t/Incorrect-warning-when-using-standard-st/673948).
|
||||
// TODO(nicohartmann@): Change to 'using std::string_literals::operator""s;'
|
||||
@ -291,6 +294,8 @@ VisitResult ImplementationVisitor::InlineMacro(
|
||||
DCHECK(macro->IsMethod());
|
||||
parameter_bindings.Add(kThisParameterName, LocalValue{*this_reference},
|
||||
true);
|
||||
// TODO(v8:12261): Tracking 'this'-binding for kythe led to a few weird
|
||||
// issues. Review to fully support 'this' in methods.
|
||||
}
|
||||
|
||||
size_t count = 0;
|
||||
@ -298,17 +303,24 @@ VisitResult ImplementationVisitor::InlineMacro(
|
||||
if (this_reference && count == signature.implicit_count) count++;
|
||||
const bool mark_as_used = signature.implicit_count > count;
|
||||
const Identifier* name = macro->parameter_names()[count++];
|
||||
parameter_bindings.Add(name,
|
||||
LocalValue{LocationReference::Temporary(
|
||||
arg, "parameter " + name->value)},
|
||||
mark_as_used);
|
||||
Binding<LocalValue>* binding =
|
||||
parameter_bindings.Add(name,
|
||||
LocalValue{LocationReference::Temporary(
|
||||
arg, "parameter " + name->value)},
|
||||
mark_as_used);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddBindingDefinition(binding);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK_EQ(label_blocks.size(), signature.labels.size());
|
||||
for (size_t i = 0; i < signature.labels.size(); ++i) {
|
||||
const LabelDeclaration& label_info = signature.labels[i];
|
||||
label_bindings.Add(label_info.name,
|
||||
LocalLabel{label_blocks[i], label_info.types});
|
||||
Binding<LocalLabel>* binding = label_bindings.Add(
|
||||
label_info.name, LocalLabel{label_blocks[i], label_info.types});
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddBindingDefinition(binding);
|
||||
}
|
||||
}
|
||||
|
||||
Block* macro_end;
|
||||
@ -542,11 +554,14 @@ std::string AddParameter(size_t i, Builtin* builtin,
|
||||
std::string external_name = "parameter" + std::to_string(i);
|
||||
parameters->Push(external_name);
|
||||
StackRange range = parameter_types->PushMany(LowerType(type));
|
||||
parameter_bindings->Add(
|
||||
Binding<LocalValue>* binding = parameter_bindings->Add(
|
||||
name,
|
||||
LocalValue{LocationReference::Temporary(VisitResult(type, range),
|
||||
"parameter " + name->value)},
|
||||
mark_as_used);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddBindingDefinition(binding);
|
||||
}
|
||||
return external_name;
|
||||
}
|
||||
|
||||
@ -1005,6 +1020,9 @@ const Type* ImplementationVisitor::Visit(GotoStatement* stmt) {
|
||||
LanguageServerData::AddDefinition(stmt->label->pos,
|
||||
label->declaration_position());
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddBindingUse(stmt->label->pos, label);
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
StackRange arguments = assembler().TopRange(0);
|
||||
@ -2230,6 +2248,9 @@ LocationReference ImplementationVisitor::GenerateFieldAccess(
|
||||
if (GlobalContext::collect_language_server_data() && pos.has_value()) {
|
||||
LanguageServerData::AddDefinition(*pos, field.pos);
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data() && pos.has_value()) {
|
||||
KytheData::AddClassFieldUse(*pos, &field);
|
||||
}
|
||||
if (field.const_qualified) {
|
||||
VisitResult t_value = ProjectStructField(reference.variable(), fieldname);
|
||||
return LocationReference::Temporary(
|
||||
@ -2326,6 +2347,9 @@ LocationReference ImplementationVisitor::GenerateFieldAccess(
|
||||
if (GlobalContext::collect_language_server_data() && pos.has_value()) {
|
||||
LanguageServerData::AddDefinition(*pos, field.pos);
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddClassFieldUse(*pos, &field);
|
||||
}
|
||||
return GenerateFieldReference(object_result, field, *class_type);
|
||||
}
|
||||
}
|
||||
@ -2367,6 +2391,13 @@ LocationReference ImplementationVisitor::GetLocationReference(
|
||||
LanguageServerData::AddDefinition(expr->name->pos,
|
||||
(*value)->declaration_position());
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
if (!expr->IsThis()) {
|
||||
DCHECK_EQ(expr->name->pos.end.column - expr->name->pos.start.column,
|
||||
expr->name->value.length());
|
||||
KytheData::AddBindingUse(expr->name->pos, *value);
|
||||
}
|
||||
}
|
||||
if (expr->generic_arguments.size() != 0) {
|
||||
ReportError("cannot have generic parameters on local name ",
|
||||
expr->name);
|
||||
@ -2385,6 +2416,7 @@ LocationReference ImplementationVisitor::GetLocationReference(
|
||||
LanguageServerData::AddDefinition(expr->name->pos,
|
||||
(*builtin)->Position());
|
||||
}
|
||||
// TODO(v8:12261): Consider collecting KytheData here.
|
||||
return LocationReference::Temporary(GetBuiltinCode(*builtin),
|
||||
"builtin " + expr->name->value);
|
||||
}
|
||||
@ -2411,6 +2443,9 @@ LocationReference ImplementationVisitor::GetLocationReference(
|
||||
LanguageServerData::AddDefinition(expr->name->pos, value->name()->pos);
|
||||
}
|
||||
if (auto* constant = NamespaceConstant::DynamicCast(value)) {
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddConstantUse(expr->name->pos, constant);
|
||||
}
|
||||
if (constant->type()->IsConstexpr()) {
|
||||
return LocationReference::Temporary(
|
||||
VisitResult(constant->type(), constant->external_name() + "(state_)"),
|
||||
@ -2424,6 +2459,9 @@ LocationReference ImplementationVisitor::GetLocationReference(
|
||||
"namespace constant " + expr->name->value);
|
||||
}
|
||||
ExternConstant* constant = ExternConstant::cast(value);
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddConstantUse(expr->name->pos, constant);
|
||||
}
|
||||
return LocationReference::Temporary(constant->value(),
|
||||
"extern value " + expr->name->value);
|
||||
}
|
||||
@ -3135,6 +3173,12 @@ VisitResult ImplementationVisitor::Visit(CallExpression* expr,
|
||||
LanguageServerData::AddDefinition(expr->callee->name->pos,
|
||||
callable->IdentifierPosition());
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
Callable* callable = LookupCallable(name, Declarations::Lookup(name),
|
||||
arguments, specialization_types);
|
||||
Callable* caller = CurrentCallable::Get();
|
||||
KytheData::AddCall(caller, expr->callee->name->pos, callable);
|
||||
}
|
||||
if (expr->callee->name->value == "!" && arguments.parameters.size() == 1) {
|
||||
PropagateBitfieldMark(expr->arguments[0], expr);
|
||||
}
|
||||
@ -3178,6 +3222,10 @@ VisitResult ImplementationVisitor::Visit(CallMethodExpression* expr) {
|
||||
LanguageServerData::AddDefinition(expr->method->name->pos,
|
||||
callable->IdentifierPosition());
|
||||
}
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
Callable* caller = CurrentCallable::Get();
|
||||
KytheData::AddCall(caller, expr->method->name->pos, callable);
|
||||
}
|
||||
return scope.Yield(GenerateCall(callable, target, arguments, {}, false));
|
||||
}
|
||||
|
||||
@ -3268,6 +3316,7 @@ std::vector<Binding<LocalLabel>*> ImplementationVisitor::LabelsFromIdentifiers(
|
||||
LanguageServerData::AddDefinition(name->pos,
|
||||
label->declaration_position());
|
||||
}
|
||||
// TODO(v8:12261): Might have to track KytheData here.
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@ -3548,7 +3597,8 @@ void ImplementationVisitor::GenerateBuiltinDefinitionsAndInterfaceDescriptors(
|
||||
Declarations::FindSomeInternalBuiltinWithType(type);
|
||||
if (!example_builtin) {
|
||||
CurrentSourcePosition::Scope current_source_position(
|
||||
SourcePosition{CurrentSourceFile::Get(), {-1, -1}, {-1, -1}});
|
||||
SourcePosition{CurrentSourceFile::Get(), LineAndColumn::Invalid(),
|
||||
LineAndColumn::Invalid()});
|
||||
ReportError("unable to find any builtin with type \"", *type, "\"");
|
||||
}
|
||||
builtin_definitions << " V(" << type->function_pointer_type_id() << ","
|
||||
|
@ -228,6 +228,8 @@ struct LayoutForInitialization {
|
||||
VisitResult size;
|
||||
};
|
||||
|
||||
extern uint64_t next_unique_binding_index;
|
||||
|
||||
template <class T>
|
||||
class Binding;
|
||||
|
||||
@ -262,7 +264,8 @@ class Binding : public T {
|
||||
name_(name),
|
||||
previous_binding_(this),
|
||||
used_(false),
|
||||
written_(false) {
|
||||
written_(false),
|
||||
unique_index_(next_unique_binding_index++) {
|
||||
std::swap(previous_binding_, manager_->current_bindings_[name]);
|
||||
}
|
||||
template <class... Args>
|
||||
@ -300,6 +303,8 @@ class Binding : public T {
|
||||
bool Written() const { return written_; }
|
||||
void SetWritten() { written_ = true; }
|
||||
|
||||
uint64_t unique_index() const { return unique_index_; }
|
||||
|
||||
private:
|
||||
bool SkipLintCheck() const { return name_.length() > 0 && name_[0] == '_'; }
|
||||
|
||||
@ -309,26 +314,31 @@ class Binding : public T {
|
||||
SourcePosition declaration_position_ = CurrentSourcePosition::Get();
|
||||
bool used_;
|
||||
bool written_;
|
||||
uint64_t unique_index_;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
class BlockBindings {
|
||||
public:
|
||||
explicit BlockBindings(BindingsManager<T>* manager) : manager_(manager) {}
|
||||
void Add(std::string name, T value, bool mark_as_used = false) {
|
||||
Binding<T>* Add(std::string name, T value, bool mark_as_used = false) {
|
||||
ReportErrorIfAlreadyBound(name);
|
||||
auto binding =
|
||||
std::make_unique<Binding<T>>(manager_, name, std::move(value));
|
||||
Binding<T>* result = binding.get();
|
||||
if (mark_as_used) binding->SetUsed();
|
||||
bindings_.push_back(std::move(binding));
|
||||
return result;
|
||||
}
|
||||
|
||||
void Add(const Identifier* name, T value, bool mark_as_used = false) {
|
||||
Binding<T>* Add(const Identifier* name, T value, bool mark_as_used = false) {
|
||||
ReportErrorIfAlreadyBound(name->value);
|
||||
auto binding =
|
||||
std::make_unique<Binding<T>>(manager_, name, std::move(value));
|
||||
Binding<T>* result = binding.get();
|
||||
if (mark_as_used) binding->SetUsed();
|
||||
bindings_.push_back(std::move(binding));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Binding<T>*> bindings() const {
|
||||
|
187
src/torque/kythe-data.cc
Normal file
187
src/torque/kythe-data.cc
Normal file
@ -0,0 +1,187 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/torque/kythe-data.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace torque {
|
||||
|
||||
DEFINE_CONTEXTUAL_VARIABLE(KytheData)
|
||||
|
||||
namespace {
|
||||
|
||||
KythePosition MakeKythePosition(const SourcePosition& pos) {
|
||||
KythePosition p;
|
||||
if (pos.source.IsValid()) {
|
||||
p.file_path = SourceFileMap::PathFromV8Root(pos.source);
|
||||
} else {
|
||||
p.file_path = "UNKNOWN";
|
||||
}
|
||||
p.start_offset = pos.start.offset;
|
||||
p.end_offset = pos.end.offset;
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Constants
|
||||
kythe_entity_t KytheData::AddConstantDefinition(const Value* constant) {
|
||||
DCHECK(constant->IsNamespaceConstant() || constant->IsExternConstant());
|
||||
KytheData* that = &KytheData::Get();
|
||||
// Check if we know the constant already.
|
||||
auto it = that->constants_.find(constant);
|
||||
if (it != that->constants_.end()) return it->second;
|
||||
|
||||
// Register this constant.
|
||||
KythePosition pos = MakeKythePosition(constant->name()->pos);
|
||||
kythe_entity_t constant_id = that->consumer_->AddDefinition(
|
||||
KytheConsumer::Kind::Constant, constant->name()->value, pos);
|
||||
that->constants_.insert(it, std::make_pair(constant, constant_id));
|
||||
return constant_id;
|
||||
}
|
||||
|
||||
void KytheData::AddConstantUse(SourcePosition use_position,
|
||||
const Value* constant) {
|
||||
DCHECK(constant->IsNamespaceConstant() || constant->IsExternConstant());
|
||||
KytheData* that = &Get();
|
||||
kythe_entity_t constant_id = AddConstantDefinition(constant);
|
||||
KythePosition use_pos = MakeKythePosition(use_position);
|
||||
that->consumer_->AddUse(KytheConsumer::Kind::Constant, constant_id, use_pos);
|
||||
}
|
||||
|
||||
// Callables
|
||||
kythe_entity_t KytheData::AddFunctionDefinition(Callable* callable) {
|
||||
KytheData* that = &KytheData::Get();
|
||||
// Check if we know the caller already.
|
||||
auto it = that->callables_.find(callable);
|
||||
if (it != that->callables_.end()) return it->second;
|
||||
|
||||
// Register this callable.
|
||||
auto ident_pos = callable->IdentifierPosition();
|
||||
kythe_entity_t callable_id = that->consumer_->AddDefinition(
|
||||
KytheConsumer::Kind::Function, callable->ExternalName(),
|
||||
MakeKythePosition(ident_pos));
|
||||
that->callables_.insert(it, std::make_pair(callable, callable_id));
|
||||
return callable_id;
|
||||
}
|
||||
|
||||
void KytheData::AddCall(Callable* caller, SourcePosition call_position,
|
||||
Callable* callee) {
|
||||
if (!caller) return; // Ignore those for now.
|
||||
DCHECK_NOT_NULL(caller);
|
||||
DCHECK_NOT_NULL(callee);
|
||||
KytheData* that = &Get();
|
||||
if (call_position.source.IsValid()) {
|
||||
kythe_entity_t caller_id = AddFunctionDefinition(caller);
|
||||
kythe_entity_t callee_id = AddFunctionDefinition(callee);
|
||||
|
||||
KythePosition call_pos = MakeKythePosition(call_position);
|
||||
that->consumer_->AddCall(KytheConsumer::Kind::Function, caller_id, call_pos,
|
||||
callee_id);
|
||||
}
|
||||
}
|
||||
|
||||
// Class fields
|
||||
kythe_entity_t KytheData::AddClassFieldDefinition(const Field* field) {
|
||||
DCHECK(field);
|
||||
KytheData* that = &KytheData::Get();
|
||||
// Check if we know that field already.
|
||||
auto it = that->class_fields_.find(field);
|
||||
if (it != that->class_fields_.end()) return it->second;
|
||||
// Register this field.
|
||||
KythePosition pos = MakeKythePosition(field->pos);
|
||||
kythe_entity_t field_id = that->consumer_->AddDefinition(
|
||||
KytheConsumer::Kind::ClassField, field->name_and_type.name, pos);
|
||||
that->class_fields_.insert(it, std::make_pair(field, field_id));
|
||||
return field_id;
|
||||
}
|
||||
|
||||
void KytheData::AddClassFieldUse(SourcePosition use_position,
|
||||
const Field* field) {
|
||||
DCHECK(field);
|
||||
KytheData* that = &KytheData::Get();
|
||||
kythe_entity_t field_id = AddClassFieldDefinition(field);
|
||||
|
||||
KythePosition use_pos = MakeKythePosition(use_position);
|
||||
that->consumer_->AddUse(KytheConsumer::Kind::ClassField, field_id, use_pos);
|
||||
}
|
||||
|
||||
// Bindings
|
||||
kythe_entity_t KytheData::AddBindingDefinition(Binding<LocalValue>* binding) {
|
||||
CHECK(binding);
|
||||
const uint64_t binding_index = binding->unique_index();
|
||||
return AddBindingDefinitionImpl(binding_index, binding->name(),
|
||||
binding->declaration_position());
|
||||
}
|
||||
|
||||
kythe_entity_t KytheData::AddBindingDefinition(Binding<LocalLabel>* binding) {
|
||||
CHECK(binding);
|
||||
const uint64_t binding_index = binding->unique_index();
|
||||
return AddBindingDefinitionImpl(binding_index, binding->name(),
|
||||
binding->declaration_position());
|
||||
}
|
||||
|
||||
kythe_entity_t KytheData::AddBindingDefinitionImpl(
|
||||
uint64_t binding_index, const std::string& name,
|
||||
const SourcePosition& ident_pos) {
|
||||
KytheData* that = &KytheData::Get();
|
||||
// Check if we know the binding already.
|
||||
auto it = that->local_bindings_.find(binding_index);
|
||||
if (it != that->local_bindings_.end()) return it->second;
|
||||
// Register this binding.
|
||||
kythe_entity_t binding_id = that->consumer_->AddDefinition(
|
||||
KytheConsumer::Kind::Variable, name, MakeKythePosition(ident_pos));
|
||||
that->local_bindings_.insert(it, std::make_pair(binding_index, binding_id));
|
||||
return binding_id;
|
||||
}
|
||||
|
||||
void KytheData::AddBindingUse(SourcePosition use_position,
|
||||
Binding<LocalValue>* binding) {
|
||||
CHECK(binding);
|
||||
KytheData* that = &KytheData::Get();
|
||||
kythe_entity_t binding_id = AddBindingDefinition(binding);
|
||||
|
||||
KythePosition use_pos = MakeKythePosition(use_position);
|
||||
that->consumer_->AddUse(KytheConsumer::Kind::Variable, binding_id, use_pos);
|
||||
}
|
||||
|
||||
void KytheData::AddBindingUse(SourcePosition use_position,
|
||||
Binding<LocalLabel>* binding) {
|
||||
CHECK(binding);
|
||||
KytheData* that = &KytheData::Get();
|
||||
kythe_entity_t binding_id = AddBindingDefinition(binding);
|
||||
|
||||
KythePosition use_pos = MakeKythePosition(use_position);
|
||||
that->consumer_->AddUse(KytheConsumer::Kind::Variable, binding_id, use_pos);
|
||||
}
|
||||
|
||||
// Types
|
||||
kythe_entity_t KytheData::AddTypeDefinition(const Declarable* type_decl) {
|
||||
CHECK(type_decl);
|
||||
KytheData* that = &KytheData::Get();
|
||||
// Check if we know that type already.
|
||||
auto it = that->types_.find(type_decl);
|
||||
if (it != that->types_.end()) return it->second;
|
||||
// Register this type.
|
||||
KythePosition pos = MakeKythePosition(type_decl->IdentifierPosition());
|
||||
kythe_entity_t type_id = that->consumer_->AddDefinition(
|
||||
KytheConsumer::Kind::Type, type_decl->type_name(), pos);
|
||||
that->types_.insert(it, std::make_pair(type_decl, type_id));
|
||||
return type_id;
|
||||
}
|
||||
|
||||
void KytheData::AddTypeUse(SourcePosition use_position,
|
||||
const Declarable* type_decl) {
|
||||
CHECK(type_decl);
|
||||
KytheData* that = &KytheData::Get();
|
||||
kythe_entity_t type_id = AddTypeDefinition(type_decl);
|
||||
|
||||
KythePosition use_pos = MakeKythePosition(use_position);
|
||||
that->consumer_->AddUse(KytheConsumer::Kind::Type, type_id, use_pos);
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
110
src/torque/kythe-data.h
Normal file
110
src/torque/kythe-data.h
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef V8_TORQUE_KYTHE_DATA_H_
|
||||
#define V8_TORQUE_KYTHE_DATA_H_
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "src/torque/ast.h"
|
||||
#include "src/torque/contextual.h"
|
||||
#include "src/torque/global-context.h"
|
||||
#include "src/torque/implementation-visitor.h"
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace torque {
|
||||
|
||||
struct KythePosition {
|
||||
std::string file_path;
|
||||
uint64_t start_offset;
|
||||
uint64_t end_offset;
|
||||
};
|
||||
|
||||
using kythe_entity_t = uint64_t;
|
||||
|
||||
class KytheConsumer {
|
||||
public:
|
||||
enum class Kind {
|
||||
Unspecified,
|
||||
Constant,
|
||||
Function,
|
||||
ClassField,
|
||||
Variable,
|
||||
Type,
|
||||
};
|
||||
|
||||
virtual ~KytheConsumer() = 0;
|
||||
|
||||
virtual kythe_entity_t AddDefinition(Kind kind, std::string name,
|
||||
KythePosition pos) = 0;
|
||||
|
||||
virtual void AddUse(Kind kind, kythe_entity_t entity,
|
||||
KythePosition use_pos) = 0;
|
||||
virtual void AddCall(Kind kind, kythe_entity_t caller_entity,
|
||||
KythePosition call_pos,
|
||||
kythe_entity_t callee_entity) = 0;
|
||||
};
|
||||
inline KytheConsumer::~KytheConsumer() = default;
|
||||
|
||||
class KytheData : public ContextualClass<KytheData> {
|
||||
public:
|
||||
KytheData() = default;
|
||||
|
||||
static void SetConsumer(KytheConsumer* consumer) {
|
||||
Get().consumer_ = consumer;
|
||||
}
|
||||
|
||||
// Constants
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddConstantDefinition(
|
||||
const Value* constant);
|
||||
V8_EXPORT_PRIVATE static void AddConstantUse(SourcePosition use_position,
|
||||
const Value* constant);
|
||||
// Callables
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddFunctionDefinition(
|
||||
Callable* callable);
|
||||
V8_EXPORT_PRIVATE static void AddCall(Callable* caller,
|
||||
SourcePosition call_position,
|
||||
Callable* callee);
|
||||
// Class fields
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddClassFieldDefinition(
|
||||
const Field* field);
|
||||
V8_EXPORT_PRIVATE static void AddClassFieldUse(SourcePosition use_position,
|
||||
const Field* field);
|
||||
// Bindings
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddBindingDefinition(
|
||||
Binding<LocalValue>* binding);
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddBindingDefinition(
|
||||
Binding<LocalLabel>* binding);
|
||||
V8_EXPORT_PRIVATE static void AddBindingUse(SourcePosition use_position,
|
||||
Binding<LocalValue>* binding);
|
||||
V8_EXPORT_PRIVATE static void AddBindingUse(SourcePosition use_position,
|
||||
Binding<LocalLabel>* binding);
|
||||
|
||||
// Types
|
||||
V8_EXPORT_PRIVATE static kythe_entity_t AddTypeDefinition(
|
||||
const Declarable* type_decl);
|
||||
V8_EXPORT_PRIVATE static void AddTypeUse(SourcePosition use_position,
|
||||
const Declarable* type_decl);
|
||||
|
||||
private:
|
||||
static kythe_entity_t AddBindingDefinitionImpl(
|
||||
uint64_t binding_index, const std::string& name,
|
||||
const SourcePosition& ident_pos);
|
||||
|
||||
KytheConsumer* consumer_;
|
||||
std::unordered_map<const Value*, kythe_entity_t> constants_;
|
||||
std::unordered_map<Callable*, kythe_entity_t> callables_;
|
||||
|
||||
std::unordered_map<const Field*, std::set<SourcePosition>> field_uses_;
|
||||
std::unordered_map<uint64_t, kythe_entity_t> local_bindings_;
|
||||
std::unordered_map<const Declarable*, kythe_entity_t> types_;
|
||||
std::unordered_map<const Field*, kythe_entity_t> class_fields_;
|
||||
};
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_TORQUE_KYTHE_DATA_H_
|
@ -279,8 +279,9 @@ void HandleGotoDefinitionRequest(GotoDefinitionRequest request,
|
||||
return;
|
||||
}
|
||||
|
||||
LineAndColumn pos{request.params().position().line(),
|
||||
request.params().position().character()};
|
||||
auto pos =
|
||||
LineAndColumn::WithUnknownOffset(request.params().position().line(),
|
||||
request.params().position().character());
|
||||
|
||||
if (auto maybe_definition = LanguageServerData::FindDefinition(id, pos)) {
|
||||
SourcePosition definition = *maybe_definition;
|
||||
|
@ -30,16 +30,27 @@ class SourceId {
|
||||
};
|
||||
|
||||
struct LineAndColumn {
|
||||
static constexpr int kUnknownOffset = -1;
|
||||
|
||||
int offset;
|
||||
int line;
|
||||
int column;
|
||||
|
||||
static LineAndColumn Invalid() { return {-1, -1}; }
|
||||
static LineAndColumn Invalid() { return {-1, -1, -1}; }
|
||||
static LineAndColumn WithUnknownOffset(int line, int column) {
|
||||
return {kUnknownOffset, line, column};
|
||||
}
|
||||
|
||||
bool operator==(const LineAndColumn& other) const {
|
||||
return line == other.line && column == other.column;
|
||||
if (offset == kUnknownOffset || other.offset == kUnknownOffset) {
|
||||
return line == other.line && column == other.column;
|
||||
}
|
||||
DCHECK_EQ(offset == other.offset,
|
||||
line == other.line && column == other.column);
|
||||
return offset == other.offset;
|
||||
}
|
||||
bool operator!=(const LineAndColumn& other) const {
|
||||
return !(*this == other);
|
||||
return !operator==(other);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -50,6 +50,9 @@ void CompileCurrentAst(TorqueCompilerOptions options) {
|
||||
if (options.collect_language_server_data) {
|
||||
GlobalContext::SetCollectLanguageServerData();
|
||||
}
|
||||
if (options.collect_kythe_data) {
|
||||
GlobalContext::SetCollectKytheData();
|
||||
}
|
||||
if (options.force_assert_statements) {
|
||||
GlobalContext::SetForceAssertStatements();
|
||||
}
|
||||
@ -161,6 +164,38 @@ TorqueCompilerResult CompileTorque(std::vector<std::string> files,
|
||||
return result;
|
||||
}
|
||||
|
||||
TorqueCompilerResult CompileTorqueForKythe(
|
||||
std::vector<TorqueCompilationUnit> units, TorqueCompilerOptions options,
|
||||
KytheConsumer* consumer) {
|
||||
SourceFileMap::Scope source_map_scope(options.v8_root);
|
||||
CurrentSourceFile::Scope unknown_source_file_scope(SourceId::Invalid());
|
||||
CurrentAst::Scope ast_scope;
|
||||
TorqueMessages::Scope messages_scope;
|
||||
LanguageServerData::Scope server_data_scope;
|
||||
KytheData::Scope kythe_scope;
|
||||
|
||||
KytheData::Get().SetConsumer(consumer);
|
||||
|
||||
TorqueCompilerResult result;
|
||||
try {
|
||||
for (const auto& unit : units) {
|
||||
SourceId source_id = SourceFileMap::AddSource(unit.source_file_path);
|
||||
CurrentSourceFile::Scope source_id_scope(source_id);
|
||||
ParseTorque(unit.file_content);
|
||||
}
|
||||
CompileCurrentAst(options);
|
||||
} catch (TorqueAbortCompilation&) {
|
||||
// Do nothing. The relevant TorqueMessage is part of the
|
||||
// TorqueMessages contextual.
|
||||
}
|
||||
|
||||
result.source_file_map = SourceFileMap::Get();
|
||||
result.language_server_data = std::move(LanguageServerData::Get());
|
||||
result.messages = std::move(TorqueMessages::Get());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "src/torque/ast.h"
|
||||
#include "src/torque/contextual.h"
|
||||
#include "src/torque/kythe-data.h"
|
||||
#include "src/torque/server-data.h"
|
||||
#include "src/torque/source-positions.h"
|
||||
#include "src/torque/utils.h"
|
||||
@ -19,6 +20,7 @@ struct TorqueCompilerOptions {
|
||||
std::string output_directory = "";
|
||||
std::string v8_root = "";
|
||||
bool collect_language_server_data = false;
|
||||
bool collect_kythe_data = false;
|
||||
|
||||
// assert(...) are only generated for debug builds. The provide
|
||||
// language server support for statements inside asserts, this flag
|
||||
@ -52,10 +54,18 @@ struct TorqueCompilerResult {
|
||||
std::vector<TorqueMessage> messages;
|
||||
};
|
||||
|
||||
struct TorqueCompilationUnit {
|
||||
std::string source_file_path;
|
||||
std::string file_content;
|
||||
};
|
||||
|
||||
V8_EXPORT_PRIVATE TorqueCompilerResult
|
||||
CompileTorque(const std::string& source, TorqueCompilerOptions options);
|
||||
TorqueCompilerResult CompileTorque(std::vector<std::string> files,
|
||||
TorqueCompilerOptions options);
|
||||
V8_EXPORT_PRIVATE TorqueCompilerResult CompileTorqueForKythe(
|
||||
std::vector<TorqueCompilationUnit> units, TorqueCompilerOptions options,
|
||||
KytheConsumer* kythe_consumer);
|
||||
|
||||
} // namespace torque
|
||||
} // namespace internal
|
||||
|
@ -32,7 +32,7 @@ struct ExpressionWithSource {
|
||||
|
||||
struct TypeswitchCase {
|
||||
SourcePosition pos;
|
||||
base::Optional<std::string> name;
|
||||
base::Optional<Identifier*> name;
|
||||
TypeExpression* type;
|
||||
Statement* block;
|
||||
};
|
||||
@ -313,9 +313,10 @@ void CheckNotDeferredStatement(Statement* statement) {
|
||||
TypeExpression* AddConstexpr(TypeExpression* type) {
|
||||
BasicTypeExpression* basic = BasicTypeExpression::DynamicCast(type);
|
||||
if (!basic) Error("Unsupported extends clause.").Throw();
|
||||
return MakeNode<BasicTypeExpression>(basic->namespace_qualification,
|
||||
CONSTEXPR_TYPE_PREFIX + basic->name,
|
||||
basic->generic_arguments);
|
||||
return MakeNode<BasicTypeExpression>(
|
||||
basic->namespace_qualification,
|
||||
MakeNode<Identifier>(CONSTEXPR_TYPE_PREFIX + basic->name->value),
|
||||
basic->generic_arguments);
|
||||
}
|
||||
|
||||
Expression* MakeCall(IdentifierExpression* callee,
|
||||
@ -382,12 +383,11 @@ base::Optional<ParseResult> MakeCall(ParseResultIterator* child_results) {
|
||||
|
||||
base::Optional<ParseResult> MakeMethodCall(ParseResultIterator* child_results) {
|
||||
auto this_arg = child_results->NextAs<Expression*>();
|
||||
auto callee = child_results->NextAs<std::string>();
|
||||
auto callee = child_results->NextAs<Identifier*>();
|
||||
auto args = child_results->NextAs<std::vector<Expression*>>();
|
||||
auto otherwise = child_results->NextAs<std::vector<Statement*>>();
|
||||
return ParseResult{
|
||||
MakeCall(MakeNode<IdentifierExpression>(MakeNode<Identifier>(callee)),
|
||||
this_arg, args, otherwise)};
|
||||
return ParseResult{MakeCall(MakeNode<IdentifierExpression>(callee), this_arg,
|
||||
args, otherwise)};
|
||||
}
|
||||
|
||||
base::Optional<ParseResult> MakeNewExpression(
|
||||
@ -525,7 +525,8 @@ base::Optional<ParseResult> MakeDebugStatement(
|
||||
|
||||
base::Optional<ParseResult> MakeVoidType(ParseResultIterator* child_results) {
|
||||
TypeExpression* result = MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, "void", std::vector<TypeExpression*>{});
|
||||
std::vector<std::string>{}, MakeNode<Identifier>("void"),
|
||||
std::vector<TypeExpression*>{});
|
||||
return ParseResult{result};
|
||||
}
|
||||
|
||||
@ -1009,16 +1010,15 @@ base::Optional<ParseResult> MakeClassDeclaration(
|
||||
(flags & ClassFlag::kIsShape) == 0) {
|
||||
ParameterList parameters;
|
||||
parameters.names.push_back(MakeNode<Identifier>("obj"));
|
||||
parameters.types.push_back(
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, "HeapObject",
|
||||
std::vector<TypeExpression*>{}));
|
||||
parameters.types.push_back(MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, MakeNode<Identifier>("HeapObject"),
|
||||
std::vector<TypeExpression*>{}));
|
||||
LabelAndTypesVector labels;
|
||||
labels.push_back(LabelAndTypes{MakeNode<Identifier>("CastError"),
|
||||
std::vector<TypeExpression*>{}});
|
||||
|
||||
TypeExpression* class_type =
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, name->value,
|
||||
std::vector<TypeExpression*>{});
|
||||
TypeExpression* class_type = MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, name, std::vector<TypeExpression*>{});
|
||||
|
||||
std::vector<std::string> namespace_qualification{
|
||||
TORQUE_INTERNAL_NAMESPACE_STRING};
|
||||
@ -1043,9 +1043,8 @@ base::Optional<ParseResult> MakeClassDeclaration(
|
||||
auto cast_body = MakeNode<ReturnStatement>(value);
|
||||
|
||||
std::vector<TypeExpression*> generic_parameters;
|
||||
generic_parameters.push_back(
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{}, name->value,
|
||||
std::vector<TypeExpression*>{}));
|
||||
generic_parameters.push_back(MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, name, std::vector<TypeExpression*>{}));
|
||||
|
||||
Declaration* specialization = MakeNode<SpecializationDeclaration>(
|
||||
false, MakeNode<Identifier>("Cast"), generic_parameters,
|
||||
@ -1194,7 +1193,8 @@ base::Optional<ParseResult> MakeBasicTypeExpression(
|
||||
child_results->NextAs<std::vector<TypeExpression*>>();
|
||||
TypeExpression* result = MakeNode<BasicTypeExpression>(
|
||||
std::move(namespace_qualification),
|
||||
is_constexpr ? GetConstexprName(name) : std::move(name),
|
||||
MakeNode<Identifier>(is_constexpr ? GetConstexprName(name)
|
||||
: std::move(name)),
|
||||
std::move(generic_arguments));
|
||||
return ParseResult{result};
|
||||
}
|
||||
@ -1217,7 +1217,8 @@ base::Optional<ParseResult> MakeReferenceTypeExpression(
|
||||
std::vector<TypeExpression*> generic_arguments{referenced_type};
|
||||
TypeExpression* result = MakeNode<BasicTypeExpression>(
|
||||
namespace_qualification,
|
||||
is_const ? CONST_REFERENCE_TYPE_STRING : MUTABLE_REFERENCE_TYPE_STRING,
|
||||
MakeNode<Identifier>(is_const ? CONST_REFERENCE_TYPE_STRING
|
||||
: MUTABLE_REFERENCE_TYPE_STRING),
|
||||
generic_arguments);
|
||||
return ParseResult{result};
|
||||
}
|
||||
@ -1315,7 +1316,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
base::nullopt);
|
||||
|
||||
TypeExpression* name_type_expression =
|
||||
MakeNode<BasicTypeExpression>(name_identifier->value);
|
||||
MakeNode<BasicTypeExpression>(name_identifier);
|
||||
name_type_expression->pos = name_identifier->pos;
|
||||
|
||||
std::vector<Declaration*> entry_decls;
|
||||
@ -1346,7 +1347,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
entry.type.value_or(*base_type_expression), base::nullopt));
|
||||
|
||||
auto entry_type = MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{name}, entry.name->value,
|
||||
std::vector<std::string>{name}, entry.name,
|
||||
std::vector<TypeExpression*>{});
|
||||
if (union_type) {
|
||||
union_type = MakeNode<UnionTypeExpression>(union_type, entry_type);
|
||||
@ -1374,7 +1375,7 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
Identifier* constexpr_type_identifier =
|
||||
MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name);
|
||||
TypeExpression* constexpr_type_expression = MakeNode<BasicTypeExpression>(
|
||||
std::string(CONSTEXPR_TYPE_PREFIX) + name);
|
||||
MakeNode<Identifier>(std::string(CONSTEXPR_TYPE_PREFIX) + name));
|
||||
base::Optional<TypeExpression*> base_constexpr_type_expression =
|
||||
base::nullopt;
|
||||
if (base_type_expression) {
|
||||
@ -1390,8 +1391,9 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
Statement* fromconstexpr_body = nullptr;
|
||||
if (generate_nonconstexpr) {
|
||||
DCHECK(base_type_expression.has_value());
|
||||
type_expr = MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, name, std::vector<TypeExpression*>{});
|
||||
type_expr = MakeNode<BasicTypeExpression>(std::vector<std::string>{},
|
||||
MakeNode<Identifier>(name),
|
||||
std::vector<TypeExpression*>{});
|
||||
|
||||
// return %RawDownCast<Enum>(%FromConstexpr<Base>(o)))
|
||||
fromconstexpr_identifier = MakeNode<Identifier>("FromConstexpr");
|
||||
@ -1440,9 +1442,10 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
MakeNode<Identifier>("constexpr constant " + entry_name);
|
||||
entry_decls.push_back(MakeNode<ExternConstDeclaration>(
|
||||
constexpr_constant_name,
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{},
|
||||
entry_constexpr_type,
|
||||
std::vector<TypeExpression*>{}),
|
||||
MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{},
|
||||
MakeNode<Identifier>(entry_constexpr_type),
|
||||
std::vector<TypeExpression*>{}),
|
||||
constexpr_generates + "::" + entry_name));
|
||||
entry_decls.push_back(MakeNode<ConstDeclaration>(
|
||||
entry.name, *entry.type,
|
||||
@ -1461,9 +1464,10 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
// }
|
||||
entry_decls.push_back(MakeNode<ExternConstDeclaration>(
|
||||
entry.name,
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{},
|
||||
entry_constexpr_type,
|
||||
std::vector<TypeExpression*>{}),
|
||||
MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{},
|
||||
MakeNode<Identifier>(entry_constexpr_type),
|
||||
std::vector<TypeExpression*>{}),
|
||||
constexpr_generates + "::" + entry_name));
|
||||
}
|
||||
|
||||
@ -1471,9 +1475,10 @@ base::Optional<ParseResult> MakeEnumDeclaration(
|
||||
// : Enum::constexpr kEntry0): Enum
|
||||
if (generate_nonconstexpr) {
|
||||
TypeExpression* entry_constexpr_type_expr =
|
||||
MakeNode<BasicTypeExpression>(std::vector<std::string>{name},
|
||||
entry_constexpr_type,
|
||||
std::vector<TypeExpression*>{});
|
||||
MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{name},
|
||||
MakeNode<Identifier>(entry_constexpr_type),
|
||||
std::vector<TypeExpression*>{});
|
||||
|
||||
ParameterList parameters;
|
||||
parameters.names.push_back(fromconstexpr_parameter_identifier);
|
||||
@ -1556,10 +1561,11 @@ base::Optional<ParseResult> MakeTypeswitchStatement(
|
||||
} else {
|
||||
case_block = current_block;
|
||||
}
|
||||
std::string name = "__case_value";
|
||||
Identifier* name =
|
||||
cases[i].name ? *cases[i].name : MakeNode<Identifier>("__case_value");
|
||||
if (cases[i].name) name = *cases[i].name;
|
||||
case_block->statements.push_back(MakeNode<VarDeclarationStatement>(
|
||||
true, MakeNode<Identifier>(name), cases[i].type, value));
|
||||
case_block->statements.push_back(
|
||||
MakeNode<VarDeclarationStatement>(true, name, cases[i].type, value));
|
||||
case_block->statements.push_back(cases[i].block);
|
||||
if (i < cases.size() - 1) {
|
||||
BlockStatement* next_block = MakeNode<BlockStatement>();
|
||||
@ -1580,11 +1586,11 @@ base::Optional<ParseResult> MakeTypeswitchStatement(
|
||||
|
||||
base::Optional<ParseResult> MakeTypeswitchCase(
|
||||
ParseResultIterator* child_results) {
|
||||
auto name = child_results->NextAs<base::Optional<std::string>>();
|
||||
auto name = child_results->NextAs<base::Optional<Identifier*>>();
|
||||
auto type = child_results->NextAs<TypeExpression*>();
|
||||
auto block = child_results->NextAs<Statement*>();
|
||||
return ParseResult{TypeswitchCase{child_results->matched_input().pos,
|
||||
std::move(name), type, block}};
|
||||
return ParseResult{
|
||||
TypeswitchCase{child_results->matched_input().pos, name, type, block}};
|
||||
}
|
||||
|
||||
base::Optional<ParseResult> MakeWhileStatement(
|
||||
@ -1722,7 +1728,8 @@ base::Optional<ParseResult> MakeCatchBlock(ParseResultIterator* child_results) {
|
||||
ParameterList parameters;
|
||||
parameters.names.push_back(MakeNode<Identifier>(variable));
|
||||
parameters.types.push_back(MakeNode<BasicTypeExpression>(
|
||||
std::vector<std::string>{}, "JSAny", std::vector<TypeExpression*>{}));
|
||||
std::vector<std::string>{}, MakeNode<Identifier>("JSAny"),
|
||||
std::vector<TypeExpression*>{}));
|
||||
parameters.has_varargs = false;
|
||||
TryHandler* result = MakeNode<TryHandler>(
|
||||
TryHandler::HandlerKind::kCatch, MakeNode<Identifier>(kCatchLabelName),
|
||||
@ -2364,10 +2371,9 @@ struct TorqueGrammar : Grammar {
|
||||
{&identifierExpression, &argumentList, optionalOtherwise}, MakeCall)};
|
||||
|
||||
// Result: Expression*
|
||||
Symbol callMethodExpression = {
|
||||
Rule({&primaryExpression, Token("."), &identifier, &argumentList,
|
||||
optionalOtherwise},
|
||||
MakeMethodCall)};
|
||||
Symbol callMethodExpression = {Rule(
|
||||
{&primaryExpression, Token("."), &name, &argumentList, optionalOtherwise},
|
||||
MakeMethodCall)};
|
||||
|
||||
// Result: NameAndExpression
|
||||
Symbol namedExpression = {
|
||||
@ -2569,7 +2575,7 @@ struct TorqueGrammar : Grammar {
|
||||
// Result: TypeswitchCase
|
||||
Symbol typeswitchCase = {
|
||||
Rule({Token("case"), Token("("),
|
||||
Optional<std::string>(Sequence({&identifier, Token(":")})), &type,
|
||||
Optional<Identifier*>(Sequence({&name, Token(":")})), &type,
|
||||
Token(")"), Token(":"), &block},
|
||||
MakeTypeswitchCase)};
|
||||
|
||||
|
@ -61,7 +61,7 @@ void TypeArgumentInference::Match(TypeExpression* parameter,
|
||||
BasicTypeExpression::DynamicCast(parameter)) {
|
||||
// If the parameter is referring to one of the type parameters, substitute
|
||||
if (basic->namespace_qualification.empty() && !basic->is_constexpr) {
|
||||
auto result = type_parameter_from_name_.find(basic->name);
|
||||
auto result = type_parameter_from_name_.find(basic->name->value);
|
||||
if (result != type_parameter_from_name_.end()) {
|
||||
size_t type_parameter_index = result->second;
|
||||
if (type_parameter_index < num_explicit_) {
|
||||
@ -92,7 +92,7 @@ void TypeArgumentInference::Match(TypeExpression* parameter,
|
||||
void TypeArgumentInference::MatchGeneric(BasicTypeExpression* parameter,
|
||||
const Type* argument_type) {
|
||||
QualifiedName qualified_name{parameter->namespace_qualification,
|
||||
parameter->name};
|
||||
parameter->name->value};
|
||||
GenericType* generic_type =
|
||||
Declarations::LookupUniqueGenericType(qualified_name);
|
||||
auto& specialized_from = argument_type->GetSpecializedFrom();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "src/common/globals.h"
|
||||
#include "src/torque/declarable.h"
|
||||
#include "src/torque/global-context.h"
|
||||
#include "src/torque/kythe-data.h"
|
||||
#include "src/torque/server-data.h"
|
||||
#include "src/torque/type-inference.h"
|
||||
#include "src/torque/type-oracle.h"
|
||||
@ -117,7 +118,10 @@ void DeclareMethods(AggregateType* container_type,
|
||||
signature.parameter_types.types.insert(
|
||||
signature.parameter_types.types.begin() + signature.implicit_count,
|
||||
container_type);
|
||||
Declarations::CreateMethod(container_type, method_name, signature, body);
|
||||
Method* m = Declarations::CreateMethod(container_type, method_name,
|
||||
signature, body);
|
||||
m->SetPosition(method->pos);
|
||||
m->SetIdentifierPosition(method->name->pos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -334,7 +338,8 @@ const ClassType* TypeVisitor::ComputeType(
|
||||
|
||||
const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
|
||||
if (auto* basic = BasicTypeExpression::DynamicCast(type_expression)) {
|
||||
QualifiedName qualified_name{basic->namespace_qualification, basic->name};
|
||||
QualifiedName qualified_name{basic->namespace_qualification,
|
||||
basic->name->value};
|
||||
auto& args = basic->generic_arguments;
|
||||
const Type* type;
|
||||
SourcePosition pos = SourcePosition::Invalid();
|
||||
@ -343,12 +348,20 @@ const Type* TypeVisitor::ComputeType(TypeExpression* type_expression) {
|
||||
auto* alias = Declarations::LookupTypeAlias(qualified_name);
|
||||
type = alias->type();
|
||||
pos = alias->GetDeclarationPosition();
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
if (alias->IsUserDefined()) {
|
||||
KytheData::AddTypeUse(basic->name->pos, alias);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto* generic_type =
|
||||
Declarations::LookupUniqueGenericType(qualified_name);
|
||||
type = TypeOracle::GetGenericTypeInstance(generic_type,
|
||||
ComputeTypeVector(args));
|
||||
pos = generic_type->declaration()->name->pos;
|
||||
if (GlobalContext::collect_kythe_data()) {
|
||||
KytheData::AddTypeUse(basic->name->pos, generic_type);
|
||||
}
|
||||
}
|
||||
|
||||
if (GlobalContext::collect_language_server_data()) {
|
||||
@ -482,7 +495,8 @@ const Type* TypeVisitor::ComputeTypeForStructExpression(
|
||||
ReportError("expected basic type expression referring to struct");
|
||||
}
|
||||
|
||||
QualifiedName qualified_name{basic->namespace_qualification, basic->name};
|
||||
QualifiedName qualified_name{basic->namespace_qualification,
|
||||
basic->name->value};
|
||||
base::Optional<GenericType*> maybe_generic_type =
|
||||
Declarations::TryLookupGenericType(qualified_name);
|
||||
|
||||
|
@ -86,8 +86,11 @@ TEST(LanguageServerMessage, GotoDefinition) {
|
||||
SourceId definition_id = SourceFileMap::AddSource("file://base.tq");
|
||||
|
||||
LanguageServerData::Scope server_data_scope;
|
||||
LanguageServerData::AddDefinition({test_id, {1, 0}, {1, 10}},
|
||||
{definition_id, {4, 1}, {4, 5}});
|
||||
LanguageServerData::AddDefinition(
|
||||
{test_id, LineAndColumn::WithUnknownOffset(1, 0),
|
||||
LineAndColumn::WithUnknownOffset(1, 10)},
|
||||
{definition_id, LineAndColumn::WithUnknownOffset(4, 1),
|
||||
LineAndColumn::WithUnknownOffset(4, 5)});
|
||||
|
||||
// First, check a unknown definition. The result must be null.
|
||||
GotoDefinitionRequest request;
|
||||
@ -171,8 +174,10 @@ TEST(LanguageServerMessage, LintErrorSendsDiagnostics) {
|
||||
|
||||
// No compilation errors but two lint warnings.
|
||||
{
|
||||
SourcePosition pos1{test_id, {0, 0}, {0, 1}};
|
||||
SourcePosition pos2{test_id, {1, 0}, {1, 1}};
|
||||
SourcePosition pos1{test_id, LineAndColumn::WithUnknownOffset(0, 0),
|
||||
LineAndColumn::WithUnknownOffset(0, 1)};
|
||||
SourcePosition pos2{test_id, LineAndColumn::WithUnknownOffset(1, 0),
|
||||
LineAndColumn::WithUnknownOffset(1, 1)};
|
||||
Lint("lint error 1").Position(pos1);
|
||||
Lint("lint error 2").Position(pos2);
|
||||
}
|
||||
|
@ -43,14 +43,20 @@ TEST(LanguageServer, GotoTypeDefinition) {
|
||||
|
||||
// Find the definition for type 'T1' of argument 'a' on line 4.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {4, 19});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(4, 19));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 7}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
|
||||
LineAndColumn::WithUnknownOffset(2, 7)}));
|
||||
|
||||
// Find the defintion for type 'T2' of argument 'b' on line 4.
|
||||
maybe_position = LanguageServerData::FindDefinition(id, {4, 26});
|
||||
maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(4, 26));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {3, 5}, {3, 7}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(3, 5),
|
||||
LineAndColumn::WithUnknownOffset(3, 7)}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoTypeDefinitionExtends) {
|
||||
@ -65,9 +71,12 @@ TEST(LanguageServer, GotoTypeDefinitionExtends) {
|
||||
|
||||
// Find the definition for 'T1' of the extends clause on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 16});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(3, 16));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 7}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
|
||||
LineAndColumn::WithUnknownOffset(2, 7)}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoTypeDefinitionNoDataForFile) {
|
||||
@ -76,7 +85,8 @@ TEST(LanguageServer, GotoTypeDefinitionNoDataForFile) {
|
||||
SourceId test_id = SourceFileMap::AddSource("test.tq");
|
||||
|
||||
// Regression test, this step should not crash.
|
||||
EXPECT_FALSE(LanguageServerData::FindDefinition(test_id, {0, 0}));
|
||||
EXPECT_FALSE(LanguageServerData::FindDefinition(
|
||||
test_id, LineAndColumn::WithUnknownOffset(0, 0)));
|
||||
}
|
||||
|
||||
// TODO(almuthanna): This test was skipped because it causes a crash when it is
|
||||
@ -99,9 +109,12 @@ TEST(LanguageServer, GotoLabelDefinitionInSignature) {
|
||||
|
||||
// Find the definition for 'Bailout' of the otherwise clause on line 6.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {6, 18});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(6, 18));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {5, 19}, {5, 26}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(5, 19),
|
||||
LineAndColumn::WithUnknownOffset(5, 26)}));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -122,9 +135,12 @@ TEST(LanguageServer, GotoLabelDefinitionInTryBlock) {
|
||||
|
||||
// Find the definition for 'Bailout' of the otherwise clause on line 6.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {6, 25});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(6, 25));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(7, 8),
|
||||
LineAndColumn::WithUnknownOffset(7, 15)}));
|
||||
}
|
||||
|
||||
// TODO(almuthanna): This test was skipped because it causes a crash when it is
|
||||
@ -143,9 +159,12 @@ TEST(LanguageServer, GotoDefinitionClassSuperType) {
|
||||
|
||||
// Find the definition for 'Tagged' of the 'extends' on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 33});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(3, 33));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 5}, {2, 11}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 5),
|
||||
LineAndColumn::WithUnknownOffset(2, 11)}));
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -162,9 +181,12 @@ TEST(LanguageServer, GotoLabelDefinitionInSignatureGotoStmt) {
|
||||
|
||||
// Find the definition for 'Fail' of the goto statement on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 7});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(3, 7));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {2, 26}, {2, 30}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(2, 26),
|
||||
LineAndColumn::WithUnknownOffset(2, 30)}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionInTryBlockGoto) {
|
||||
@ -181,9 +203,12 @@ TEST(LanguageServer, GotoLabelDefinitionInTryBlockGoto) {
|
||||
|
||||
// Find the definition for 'Bailout' of the goto statement on line 3.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {3, 13});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(3, 13));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {4, 8}, {4, 15}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(4, 8),
|
||||
LineAndColumn::WithUnknownOffset(4, 15)}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, GotoLabelDefinitionGotoInOtherwise) {
|
||||
@ -203,9 +228,12 @@ TEST(LanguageServer, GotoLabelDefinitionGotoInOtherwise) {
|
||||
|
||||
// Find the definition for 'Bailout' of the otherwise clause on line 6.
|
||||
const SourceId id = SourceFileMap::GetSourceId("dummy-filename.tq");
|
||||
auto maybe_position = LanguageServerData::FindDefinition(id, {6, 30});
|
||||
auto maybe_position = LanguageServerData::FindDefinition(
|
||||
id, LineAndColumn::WithUnknownOffset(6, 30));
|
||||
ASSERT_TRUE(maybe_position.has_value());
|
||||
EXPECT_EQ(*maybe_position, (SourcePosition{id, {7, 8}, {7, 15}}));
|
||||
EXPECT_EQ(*maybe_position,
|
||||
(SourcePosition{id, LineAndColumn::WithUnknownOffset(7, 8),
|
||||
LineAndColumn::WithUnknownOffset(7, 15)}));
|
||||
}
|
||||
|
||||
TEST(LanguageServer, SymbolsArePopulated) {
|
||||
|
@ -224,7 +224,8 @@ using SubstrWithPosition =
|
||||
SubstrWithPosition SubstrTester(const std::string& message, int line, int col) {
|
||||
// Change line and column from 1-based to 0-based.
|
||||
return {::testing::HasSubstr(message),
|
||||
LineAndColumn{line + CountPreludeLines() - 1, col - 1}};
|
||||
LineAndColumn::WithUnknownOffset(line + CountPreludeLines() - 1,
|
||||
col - 1)};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user