1// Copyright 2021 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "src/torque/kythe-data.h"
6
7namespace v8 {
8namespace internal {
9namespace torque {
10
11DEFINE_CONTEXTUAL_VARIABLE(KytheData)
12
13namespace {
14
15KythePosition MakeKythePosition(const SourcePosition& pos) {
16  KythePosition p;
17  if (pos.source.IsValid()) {
18    p.file_path = SourceFileMap::PathFromV8Root(pos.source);
19  } else {
20    p.file_path = "UNKNOWN";
21  }
22  p.start_offset = pos.start.offset;
23  p.end_offset = pos.end.offset;
24  return p;
25}
26
27}  // namespace
28
29// Constants
30kythe_entity_t KytheData::AddConstantDefinition(const Value* constant) {
31  DCHECK(constant->IsNamespaceConstant() || constant->IsExternConstant());
32  KytheData* that = &KytheData::Get();
33  // Check if we know the constant already.
34  auto it = that->constants_.find(constant);
35  if (it != that->constants_.end()) return it->second;
36
37  // Register this constant.
38  KythePosition pos = MakeKythePosition(constant->name()->pos);
39  kythe_entity_t constant_id = that->consumer_->AddDefinition(
40      KytheConsumer::Kind::Constant, constant->name()->value, pos);
41  that->constants_.insert(it, std::make_pair(constant, constant_id));
42  return constant_id;
43}
44
45void KytheData::AddConstantUse(SourcePosition use_position,
46                               const Value* constant) {
47  DCHECK(constant->IsNamespaceConstant() || constant->IsExternConstant());
48  KytheData* that = &Get();
49  kythe_entity_t constant_id = AddConstantDefinition(constant);
50  KythePosition use_pos = MakeKythePosition(use_position);
51  that->consumer_->AddUse(KytheConsumer::Kind::Constant, constant_id, use_pos);
52}
53
54// Callables
55kythe_entity_t KytheData::AddFunctionDefinition(Callable* callable) {
56  KytheData* that = &KytheData::Get();
57  // Check if we know the caller already.
58  auto it = that->callables_.find(callable);
59  if (it != that->callables_.end()) return it->second;
60
61  // Register this callable.
62  auto ident_pos = callable->IdentifierPosition();
63  kythe_entity_t callable_id = that->consumer_->AddDefinition(
64      KytheConsumer::Kind::Function, callable->ExternalName(),
65      MakeKythePosition(ident_pos));
66  that->callables_.insert(it, std::make_pair(callable, callable_id));
67  return callable_id;
68}
69
70void KytheData::AddCall(Callable* caller, SourcePosition call_position,
71                        Callable* callee) {
72  if (!caller) return;  // Ignore those for now.
73  DCHECK_NOT_NULL(caller);
74  DCHECK_NOT_NULL(callee);
75  KytheData* that = &Get();
76  if (call_position.source.IsValid()) {
77    kythe_entity_t caller_id = AddFunctionDefinition(caller);
78    kythe_entity_t callee_id = AddFunctionDefinition(callee);
79
80    KythePosition call_pos = MakeKythePosition(call_position);
81    that->consumer_->AddCall(KytheConsumer::Kind::Function, caller_id, call_pos,
82                             callee_id);
83  }
84}
85
86// Class fields
87kythe_entity_t KytheData::AddClassFieldDefinition(const Field* field) {
88  DCHECK(field);
89  KytheData* that = &KytheData::Get();
90  // Check if we know that field already.
91  auto it = that->class_fields_.find(field);
92  if (it != that->class_fields_.end()) return it->second;
93  // Register this field.
94  KythePosition pos = MakeKythePosition(field->pos);
95  kythe_entity_t field_id = that->consumer_->AddDefinition(
96      KytheConsumer::Kind::ClassField, field->name_and_type.name, pos);
97  that->class_fields_.insert(it, std::make_pair(field, field_id));
98  return field_id;
99}
100
101void KytheData::AddClassFieldUse(SourcePosition use_position,
102                                 const Field* field) {
103  DCHECK(field);
104  KytheData* that = &KytheData::Get();
105  kythe_entity_t field_id = AddClassFieldDefinition(field);
106
107  KythePosition use_pos = MakeKythePosition(use_position);
108  that->consumer_->AddUse(KytheConsumer::Kind::ClassField, field_id, use_pos);
109}
110
111// Bindings
112kythe_entity_t KytheData::AddBindingDefinition(Binding<LocalValue>* binding) {
113  CHECK(binding);
114  const uint64_t binding_index = binding->unique_index();
115  return AddBindingDefinitionImpl(binding_index, binding->name(),
116                                  binding->declaration_position());
117}
118
119kythe_entity_t KytheData::AddBindingDefinition(Binding<LocalLabel>* binding) {
120  CHECK(binding);
121  const uint64_t binding_index = binding->unique_index();
122  return AddBindingDefinitionImpl(binding_index, binding->name(),
123                                  binding->declaration_position());
124}
125
126kythe_entity_t KytheData::AddBindingDefinitionImpl(
127    uint64_t binding_index, const std::string& name,
128    const SourcePosition& ident_pos) {
129  KytheData* that = &KytheData::Get();
130  // Check if we know the binding already.
131  auto it = that->local_bindings_.find(binding_index);
132  if (it != that->local_bindings_.end()) return it->second;
133  // Register this binding.
134  kythe_entity_t binding_id = that->consumer_->AddDefinition(
135      KytheConsumer::Kind::Variable, name, MakeKythePosition(ident_pos));
136  that->local_bindings_.insert(it, std::make_pair(binding_index, binding_id));
137  return binding_id;
138}
139
140void KytheData::AddBindingUse(SourcePosition use_position,
141                              Binding<LocalValue>* binding) {
142  CHECK(binding);
143  KytheData* that = &KytheData::Get();
144  kythe_entity_t binding_id = AddBindingDefinition(binding);
145
146  KythePosition use_pos = MakeKythePosition(use_position);
147  that->consumer_->AddUse(KytheConsumer::Kind::Variable, binding_id, use_pos);
148}
149
150void KytheData::AddBindingUse(SourcePosition use_position,
151                              Binding<LocalLabel>* binding) {
152  CHECK(binding);
153  KytheData* that = &KytheData::Get();
154  kythe_entity_t binding_id = AddBindingDefinition(binding);
155
156  KythePosition use_pos = MakeKythePosition(use_position);
157  that->consumer_->AddUse(KytheConsumer::Kind::Variable, binding_id, use_pos);
158}
159
160// Types
161kythe_entity_t KytheData::AddTypeDefinition(const Declarable* type_decl) {
162  CHECK(type_decl);
163  KytheData* that = &KytheData::Get();
164  // Check if we know that type already.
165  auto it = that->types_.find(type_decl);
166  if (it != that->types_.end()) return it->second;
167  // Register this type.
168  KythePosition pos = MakeKythePosition(type_decl->IdentifierPosition());
169  kythe_entity_t type_id = that->consumer_->AddDefinition(
170      KytheConsumer::Kind::Type, type_decl->type_name(), pos);
171  that->types_.insert(it, std::make_pair(type_decl, type_id));
172  return type_id;
173}
174
175void KytheData::AddTypeUse(SourcePosition use_position,
176                           const Declarable* type_decl) {
177  CHECK(type_decl);
178  KytheData* that = &KytheData::Get();
179  kythe_entity_t type_id = AddTypeDefinition(type_decl);
180
181  KythePosition use_pos = MakeKythePosition(use_position);
182  that->consumer_->AddUse(KytheConsumer::Kind::Type, type_id, use_pos);
183}
184
185}  // namespace torque
186}  // namespace internal
187}  // namespace v8
188