Coverage Report

Created: 2025-09-04 07:34

/src/solidity/libsolidity/ast/ASTJsonExporter.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/**
19
 * @date 2017
20
 * Converts the AST into json format
21
 */
22
23
#include <libsolidity/ast/ASTJsonExporter.h>
24
25
#include <libsolidity/ast/AST.h>
26
#include <libsolidity/ast/TypeProvider.h>
27
28
#include <libyul/AsmJsonConverter.h>
29
#include <libyul/AST.h>
30
#include <libyul/backends/evm/EVMDialect.h>
31
32
#include <libsolutil/JSON.h>
33
#include <libsolutil/UTF8.h>
34
#include <libsolutil/CommonData.h>
35
#include <libsolutil/Visitor.h>
36
#include <libsolutil/Keccak256.h>
37
38
#include <boost/algorithm/string/join.hpp>
39
40
#include <utility>
41
#include <vector>
42
#include <algorithm>
43
#include <limits>
44
#include <type_traits>
45
#include <range/v3/view/map.hpp>
46
47
using namespace std::string_literals;
48
using namespace solidity::langutil;
49
using namespace solidity;
50
51
namespace
52
{
53
54
template<typename V, template<typename> typename C>
55
void addIfSet(std::vector<std::pair<std::string, Json>>& _attributes, std::string const& _name, C<V> const& _value)
56
0
{
57
0
  if constexpr (std::is_same_v<C<V>, solidity::util::SetOnce<V>>)
58
0
  {
59
0
    if (!_value.set())
60
0
      return;
61
0
  }
62
0
  else if constexpr (std::is_same_v<C<V>, std::optional<V>>)
63
0
  {
64
0
    if (!_value.has_value())
65
0
      return;
66
0
  }
67
68
0
  _attributes.emplace_back(_name, *_value);
69
0
}
Unexecuted instantiation: ASTJsonExporter.cpp:void (anonymous namespace)::addIfSet<bool, solidity::util::SetOnce>(std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, void> >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, void> > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, solidity::util::SetOnce<bool> const&)
Unexecuted instantiation: ASTJsonExporter.cpp:void (anonymous namespace)::addIfSet<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, solidity::util::SetOnce>(std::__1::vector<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, void> >, std::__1::allocator<std::__1::pair<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, nlohmann::json_abi_v3_11_3::basic_json<std::__1::map, std::__1::vector, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, bool, long, unsigned long, double, std::__1::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >, void> > > >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, solidity::util::SetOnce<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > const&)
70
71
}
72
73
namespace solidity::frontend
74
{
75
76
ASTJsonExporter::ASTJsonExporter(CompilerStack::State _stackState, std::map<std::string, unsigned> _sourceIndices):
77
  m_stackState(_stackState),
78
  m_sourceIndices(std::move(_sourceIndices))
79
0
{
80
0
}
81
82
83
void ASTJsonExporter::setJsonNode(
84
  ASTNode const& _node,
85
  std::string const& _nodeName,
86
  std::initializer_list<std::pair<std::string, Json>>&& _attributes
87
)
88
0
{
89
0
  ASTJsonExporter::setJsonNode(
90
0
    _node,
91
0
    _nodeName,
92
0
    std::vector<std::pair<std::string, Json>>(std::move(_attributes))
93
0
  );
94
0
}
95
96
void ASTJsonExporter::setJsonNode(
97
  ASTNode const& _node,
98
  std::string const& _nodeType,
99
  std::vector<std::pair<std::string, Json>>&& _attributes
100
)
101
0
{
102
0
  m_currentValue = Json::object();
103
0
  m_currentValue["id"] = nodeId(_node);
104
0
  m_currentValue["src"] = sourceLocationToString(_node.location());
105
0
  if (auto const* documented = dynamic_cast<Documented const*>(&_node))
106
0
    if (documented->documentation())
107
0
      m_currentValue["documentation"] = *documented->documentation();
108
0
  m_currentValue["nodeType"] = _nodeType;
109
0
  for (auto& e: _attributes)
110
0
    m_currentValue[e.first] = std::move(e.second);
111
0
}
112
113
std::optional<size_t> ASTJsonExporter::sourceIndexFromLocation(SourceLocation const& _location) const
114
0
{
115
0
  if (_location.sourceName && m_sourceIndices.count(*_location.sourceName))
116
0
    return m_sourceIndices.at(*_location.sourceName);
117
0
  else
118
0
    return std::nullopt;
119
0
}
120
121
std::string ASTJsonExporter::sourceLocationToString(SourceLocation const& _location) const
122
0
{
123
0
  std::optional<size_t> sourceIndexOpt = sourceIndexFromLocation(_location);
124
0
  int length = -1;
125
0
  if (_location.start >= 0 && _location.end >= 0)
126
0
    length = _location.end - _location.start;
127
0
  return std::to_string(_location.start) + ":" + std::to_string(length) + ":" + (sourceIndexOpt.has_value() ? std::to_string(sourceIndexOpt.value()) : "-1");
128
0
}
129
130
Json ASTJsonExporter::sourceLocationsToJson(std::vector<SourceLocation> const& _sourceLocations) const
131
0
{
132
0
  Json locations = Json::array();
133
134
0
  for (SourceLocation const& location: _sourceLocations)
135
0
    locations.emplace_back(sourceLocationToString(location));
136
137
0
  return locations;
138
0
}
139
140
std::string ASTJsonExporter::namePathToString(std::vector<ASTString> const& _namePath)
141
0
{
142
0
  return boost::algorithm::join(_namePath, "."s);
143
0
}
144
145
Json ASTJsonExporter::typePointerToJson(Type const* _tp, bool _withoutDataLocation)
146
0
{
147
0
  Json typeDescriptions;
148
0
  typeDescriptions["typeString"] = _tp ? Json(_tp->toString(_withoutDataLocation)) : Json();
149
0
  typeDescriptions["typeIdentifier"] = _tp ? Json(_tp->identifier()) : Json();
150
0
  return typeDescriptions;
151
152
0
}
153
Json ASTJsonExporter::typePointerToJson(std::optional<FuncCallArguments> const& _tps)
154
0
{
155
0
  if (_tps)
156
0
  {
157
0
    Json arguments = Json::array();
158
0
    for (auto const& tp: _tps->types)
159
0
      appendMove(arguments, typePointerToJson(tp));
160
0
    return arguments;
161
0
  }
162
0
  else
163
0
    return Json();
164
0
}
165
166
void ASTJsonExporter::appendExpressionAttributes(
167
  std::vector<std::pair<std::string, Json>>& _attributes,
168
  ExpressionAnnotation const& _annotation
169
)
170
0
{
171
0
  std::vector<std::pair<std::string, Json>> exprAttributes = {
172
0
    std::make_pair("typeDescriptions", typePointerToJson(_annotation.type)),
173
0
    std::make_pair("argumentTypes", typePointerToJson(_annotation.arguments))
174
0
  };
175
176
0
  addIfSet(exprAttributes, "isLValue", _annotation.isLValue);
177
0
  addIfSet(exprAttributes, "isPure", _annotation.isPure);
178
0
  addIfSet(exprAttributes, "isConstant", _annotation.isConstant);
179
180
0
  if (m_stackState > CompilerStack::State::ParsedAndImported)
181
0
    exprAttributes.emplace_back("lValueRequested", _annotation.willBeWrittenTo);
182
183
0
  _attributes += exprAttributes;
184
0
}
185
186
Json ASTJsonExporter::inlineAssemblyIdentifierToJson(std::pair<yul::Identifier const*, InlineAssemblyAnnotation::ExternalIdentifierInfo> _info) const
187
0
{
188
0
  Json tuple;
189
0
  tuple["src"] = sourceLocationToString(nativeLocationOf(*_info.first));
190
0
  tuple["declaration"] = idOrNull(_info.second.declaration);
191
0
  tuple["isSlot"] = Json(_info.second.suffix == "slot");
192
0
  tuple["isOffset"] = Json(_info.second.suffix == "offset");
193
194
0
  if (!_info.second.suffix.empty())
195
0
    tuple["suffix"] = Json(_info.second.suffix);
196
197
0
  tuple["valueSize"] = Json(static_cast<Json::number_integer_t>(_info.second.valueSize));
198
199
0
  return tuple;
200
0
}
201
202
void ASTJsonExporter::print(std::ostream& _stream, ASTNode const& _node, util::JsonFormat const& _format)
203
0
{
204
0
  _stream << util::jsonPrint(toJson(_node), _format);
205
0
}
206
207
Json ASTJsonExporter::toJson(ASTNode const& _node)
208
0
{
209
0
  _node.accept(*this);
210
0
  return util::removeNullMembers(std::move(m_currentValue));
211
0
}
212
213
Json ASTJsonExporter::toJson(ASTNode const* _node)
214
0
{
215
0
  if (!_node)
216
0
    return Json();
217
0
  return toJson(*_node);
218
0
}
219
220
bool ASTJsonExporter::visit(SourceUnit const& _node)
221
0
{
222
0
  std::vector<std::pair<std::string, Json>> attributes = {
223
0
    std::make_pair("license", _node.licenseString() ? Json(*_node.licenseString()) : Json()),
224
0
    std::make_pair("nodes", toJson(_node.nodes())),
225
0
  };
226
227
0
  if (_node.experimentalSolidity())
228
0
    attributes.emplace_back("experimentalSolidity", Json(_node.experimentalSolidity()));
229
230
0
  if (_node.annotation().exportedSymbols.set())
231
0
  {
232
0
    Json exportedSymbols = Json::object();
233
0
    for (auto const& sym: *_node.annotation().exportedSymbols)
234
0
    {
235
0
      exportedSymbols[sym.first] = Json::array();
236
0
      for (Declaration const* overload: sym.second)
237
0
        exportedSymbols[sym.first].emplace_back(nodeId(*overload));
238
0
    }
239
240
0
    attributes.emplace_back("exportedSymbols", exportedSymbols);
241
0
  };
242
243
0
  addIfSet(attributes, "absolutePath", _node.annotation().path);
244
245
0
  setJsonNode(_node, "SourceUnit", std::move(attributes));
246
247
0
  return false;
248
0
}
249
250
bool ASTJsonExporter::visit(PragmaDirective const& _node)
251
0
{
252
0
  Json literals = Json::array();
253
0
  for (auto const& literal: _node.literals())
254
0
    literals.emplace_back(literal);
255
0
  setJsonNode(_node, "PragmaDirective", {
256
0
    std::make_pair("literals", std::move(literals))
257
0
  });
258
0
  return false;
259
0
}
260
261
bool ASTJsonExporter::visit(ImportDirective const& _node)
262
0
{
263
0
  std::vector<std::pair<std::string, Json>> attributes = {
264
0
    std::make_pair("file", _node.path()),
265
0
    std::make_pair("sourceUnit", idOrNull(_node.annotation().sourceUnit)),
266
0
    std::make_pair("scope", idOrNull(_node.scope()))
267
0
  };
268
269
0
  addIfSet(attributes, "absolutePath", _node.annotation().absolutePath);
270
271
0
  attributes.emplace_back("unitAlias", _node.name());
272
0
  attributes.emplace_back("nameLocation", Json(sourceLocationToString(_node.nameLocation())));
273
274
0
  Json symbolAliases = Json::array();
275
0
  for (auto const& symbolAlias: _node.symbolAliases())
276
0
  {
277
0
    Json tuple;
278
0
    solAssert(symbolAlias.symbol, "");
279
0
    tuple["foreign"] = toJson(*symbolAlias.symbol);
280
0
    tuple["local"] =  symbolAlias.alias ? Json(*symbolAlias.alias) : Json();
281
0
    tuple["nameLocation"] = sourceLocationToString(_node.nameLocation());
282
0
    symbolAliases.emplace_back(tuple);
283
0
  }
284
0
  attributes.emplace_back("symbolAliases", std::move(symbolAliases));
285
0
  setJsonNode(_node, "ImportDirective", std::move(attributes));
286
0
  return false;
287
0
}
288
289
bool ASTJsonExporter::visit(StorageLayoutSpecifier const& _node)
290
0
{
291
0
  setJsonNode(_node, "StorageLayoutSpecifier", {
292
0
    {"baseSlotExpression", toJson(_node.baseSlotExpression())}
293
0
  });
294
0
  return false;
295
0
}
296
297
bool ASTJsonExporter::visit(ContractDefinition const& _node)
298
0
{
299
0
  std::vector<std::pair<std::string, Json>> attributes = {
300
0
    std::make_pair("name", _node.name()),
301
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
302
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
303
0
    std::make_pair("contractKind", contractKind(_node.contractKind())),
304
0
    std::make_pair("abstract", _node.abstract()),
305
0
    std::make_pair("baseContracts", toJson(_node.baseContracts())),
306
0
    std::make_pair("contractDependencies", getContainerIds(_node.annotation().contractDependencies | ranges::views::keys)),
307
    // Do not require call graph because the AST is also created for incorrect sources.
308
0
    std::make_pair("usedEvents", getContainerIds(_node.interfaceEvents(false))),
309
0
    std::make_pair("usedErrors", getContainerIds(_node.interfaceErrors(false))),
310
0
    std::make_pair("nodes", toJson(_node.subNodes())),
311
0
    std::make_pair("scope", idOrNull(_node.scope())),
312
0
    std::make_pair("storageLayout", toJson(_node.storageLayoutSpecifier()))
313
0
  };
314
0
  addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
315
316
0
  if (_node.annotation().unimplementedDeclarations.has_value())
317
0
    attributes.emplace_back("fullyImplemented", _node.annotation().unimplementedDeclarations->empty());
318
0
  if (!_node.annotation().linearizedBaseContracts.empty())
319
0
    attributes.emplace_back("linearizedBaseContracts", getContainerIds(_node.annotation().linearizedBaseContracts));
320
321
0
  if (!_node.annotation().internalFunctionIDs.empty())
322
0
  {
323
0
    Json internalFunctionIDs;
324
0
    for (auto const& [functionDefinition, internalFunctionID]: _node.annotation().internalFunctionIDs)
325
0
      internalFunctionIDs[std::to_string(functionDefinition->id())] = internalFunctionID;
326
0
    attributes.emplace_back("internalFunctionIDs", std::move(internalFunctionIDs));
327
0
  }
328
329
0
  setJsonNode(_node, "ContractDefinition", std::move(attributes));
330
0
  return false;
331
0
}
332
333
bool ASTJsonExporter::visit(IdentifierPath const& _node)
334
0
{
335
0
  Json nameLocations = Json::array();
336
337
0
  for (SourceLocation location: _node.pathLocations())
338
0
    nameLocations.emplace_back(sourceLocationToString(location));
339
340
0
  setJsonNode(_node, "IdentifierPath", {
341
0
    std::make_pair("name", namePathToString(_node.path())),
342
0
    std::make_pair("nameLocations", nameLocations),
343
0
    std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration))
344
0
  });
345
0
  return false;
346
0
}
347
348
bool ASTJsonExporter::visit(InheritanceSpecifier const& _node)
349
0
{
350
0
  setJsonNode(_node, "InheritanceSpecifier", {
351
0
    std::make_pair("baseName", toJson(_node.name())),
352
0
    std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json())
353
0
  });
354
0
  return false;
355
0
}
356
357
bool ASTJsonExporter::visit(UsingForDirective const& _node)
358
0
{
359
0
  std::vector<std::pair<std::string, Json>> attributes = {
360
0
    std::make_pair("typeName", _node.typeName() ? toJson(*_node.typeName()) : Json())
361
0
  };
362
363
0
  if (_node.usesBraces())
364
0
  {
365
0
    Json functionList = Json::array();
366
0
    for (auto&& [function, op]: _node.functionsAndOperators())
367
0
    {
368
0
      Json functionNode;
369
0
      if (!op.has_value())
370
0
        functionNode["function"] = toJson(*function);
371
0
      else
372
0
      {
373
0
        functionNode["definition"] = toJson(*function);
374
0
        functionNode["operator"] = std::string(TokenTraits::toString(*op));
375
0
      }
376
0
      functionList.emplace_back(std::move(functionNode));
377
0
    }
378
0
    attributes.emplace_back("functionList", std::move(functionList));
379
0
  }
380
0
  else
381
0
  {
382
0
    auto const& functionAndOperators = _node.functionsAndOperators();
383
0
    solAssert(_node.functionsAndOperators().size() == 1);
384
0
    solAssert(!functionAndOperators.front().second.has_value());
385
0
    attributes.emplace_back("libraryName", toJson(*(functionAndOperators.front().first)));
386
0
  }
387
0
  attributes.emplace_back("global", _node.global());
388
389
0
  setJsonNode(_node, "UsingForDirective", std::move(attributes));
390
391
0
  return false;
392
0
}
393
394
bool ASTJsonExporter::visit(StructDefinition const& _node)
395
0
{
396
0
  std::vector<std::pair<std::string, Json>> attributes = {
397
0
    std::make_pair("name", _node.name()),
398
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
399
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
400
0
    std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
401
0
    std::make_pair("members", toJson(_node.members())),
402
0
    std::make_pair("scope", idOrNull(_node.scope()))
403
0
  };
404
405
0
  addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
406
407
0
  setJsonNode(_node, "StructDefinition", std::move(attributes));
408
409
0
  return false;
410
0
}
411
412
bool ASTJsonExporter::visit(EnumDefinition const& _node)
413
0
{
414
0
  std::vector<std::pair<std::string, Json>> attributes = {
415
0
    std::make_pair("name", _node.name()),
416
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
417
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
418
0
    std::make_pair("members", toJson(_node.members()))
419
0
  };
420
421
0
  addIfSet(attributes,"canonicalName", _node.annotation().canonicalName);
422
423
0
  setJsonNode(_node, "EnumDefinition", std::move(attributes));
424
425
0
  return false;
426
0
}
427
428
bool ASTJsonExporter::visit(EnumValue const& _node)
429
0
{
430
0
  setJsonNode(_node, "EnumValue", {
431
0
    std::make_pair("name", _node.name()),
432
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
433
0
    std::make_pair("documentation", toJson(_node.documentation().get())),
434
0
  });
435
0
  return false;
436
0
}
437
438
bool ASTJsonExporter::visit(UserDefinedValueTypeDefinition const& _node)
439
0
{
440
0
  solAssert(_node.underlyingType(), "");
441
0
  std::vector<std::pair<std::string, Json>> attributes = {
442
0
    std::make_pair("name", _node.name()),
443
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
444
0
    std::make_pair("underlyingType", toJson(*_node.underlyingType()))
445
0
  };
446
0
  addIfSet(attributes, "canonicalName", _node.annotation().canonicalName);
447
448
0
  setJsonNode(_node, "UserDefinedValueTypeDefinition", std::move(attributes));
449
450
0
  return false;
451
0
}
452
453
bool ASTJsonExporter::visit(ParameterList const& _node)
454
0
{
455
0
  setJsonNode(_node, "ParameterList", {
456
0
    std::make_pair("parameters", toJson(_node.parameters()))
457
0
  });
458
0
  return false;
459
0
}
460
461
bool ASTJsonExporter::visit(OverrideSpecifier const& _node)
462
0
{
463
0
  setJsonNode(_node, "OverrideSpecifier", {
464
0
    std::make_pair("overrides", toJson(_node.overrides()))
465
0
  });
466
0
  return false;
467
0
}
468
469
bool ASTJsonExporter::visit(FunctionDefinition const& _node)
470
0
{
471
0
  std::vector<std::pair<std::string, Json>> attributes = {
472
0
    std::make_pair("name", _node.name()),
473
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
474
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
475
0
    std::make_pair("kind", _node.isFree() ? "freeFunction" : TokenTraits::toString(_node.kind())),
476
0
    std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
477
0
    std::make_pair("virtual", _node.markedVirtual()),
478
0
    std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()),
479
0
    std::make_pair("parameters", toJson(_node.parameterList())),
480
0
    std::make_pair("returnParameters", toJson(*_node.returnParameterList())),
481
0
    std::make_pair("modifiers", toJson(_node.modifiers())),
482
0
    std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json()),
483
0
    std::make_pair("implemented", _node.isImplemented()),
484
0
    std::make_pair("scope", idOrNull(_node.scope()))
485
0
  };
486
487
0
  std::optional<Visibility> visibility;
488
0
  if (_node.isConstructor())
489
0
  {
490
0
    if (_node.annotation().contract)
491
0
      visibility = _node.annotation().contract->abstract() ? Visibility::Internal : Visibility::Public;
492
0
  }
493
0
  else
494
0
    visibility = _node.visibility();
495
496
0
  if (visibility)
497
0
    attributes.emplace_back("visibility", Declaration::visibilityToString(*visibility));
498
499
0
  if (_node.isPartOfExternalInterface() && m_stackState > CompilerStack::State::ParsedAndImported)
500
0
    attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
501
0
  if (!_node.annotation().baseFunctions.empty())
502
0
    attributes.emplace_back(std::make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
503
504
0
  setJsonNode(_node, "FunctionDefinition", std::move(attributes));
505
0
  return false;
506
0
}
507
508
bool ASTJsonExporter::visit(VariableDeclaration const& _node)
509
0
{
510
0
  std::vector<std::pair<std::string, Json>> attributes = {
511
0
    std::make_pair("name", _node.name()),
512
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
513
0
    std::make_pair("typeName", toJson(_node.typeName())),
514
0
    std::make_pair("constant", _node.isConstant()),
515
0
    std::make_pair("mutability", VariableDeclaration::mutabilityToString(_node.mutability())),
516
0
    std::make_pair("stateVariable", _node.isStateVariable()),
517
0
    std::make_pair("storageLocation", location(_node.referenceLocation())),
518
0
    std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()),
519
0
    std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
520
0
    std::make_pair("value", _node.value() ? toJson(*_node.value()) : Json()),
521
0
    std::make_pair("scope", idOrNull(_node.scope())),
522
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
523
0
  };
524
0
  if (_node.isStateVariable() && _node.isPublic())
525
0
    attributes.emplace_back("functionSelector", _node.externalIdentifierHex());
526
0
  if (_node.isStateVariable() && _node.documentation())
527
0
    attributes.emplace_back("documentation", toJson(*_node.documentation()));
528
0
  if (m_inEvent)
529
0
    attributes.emplace_back("indexed", _node.isIndexed());
530
0
  if (!_node.annotation().baseFunctions.empty())
531
0
    attributes.emplace_back(std::make_pair("baseFunctions", getContainerIds(_node.annotation().baseFunctions, true)));
532
0
  setJsonNode(_node, "VariableDeclaration", std::move(attributes));
533
0
  return false;
534
0
}
535
536
bool ASTJsonExporter::visit(ModifierDefinition const& _node)
537
0
{
538
0
  std::vector<std::pair<std::string, Json>> attributes = {
539
0
    std::make_pair("name", _node.name()),
540
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
541
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
542
0
    std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
543
0
    std::make_pair("parameters", toJson(_node.parameterList())),
544
0
    std::make_pair("virtual", _node.markedVirtual()),
545
0
    std::make_pair("overrides", _node.overrides() ? toJson(*_node.overrides()) : Json()),
546
0
    std::make_pair("body", _node.isImplemented() ? toJson(_node.body()) : Json())
547
0
  };
548
0
  if (!_node.annotation().baseFunctions.empty())
549
0
    attributes.emplace_back(std::make_pair("baseModifiers", getContainerIds(_node.annotation().baseFunctions, true)));
550
0
  setJsonNode(_node, "ModifierDefinition", std::move(attributes));
551
0
  return false;
552
0
}
553
554
bool ASTJsonExporter::visit(ModifierInvocation const& _node)
555
0
{
556
0
  std::vector<std::pair<std::string, Json>> attributes{
557
0
    std::make_pair("modifierName", toJson(_node.name())),
558
0
    std::make_pair("arguments", _node.arguments() ? toJson(*_node.arguments()) : Json())
559
0
  };
560
0
  if (Declaration const* declaration = _node.name().annotation().referencedDeclaration)
561
0
  {
562
0
    if (dynamic_cast<ModifierDefinition const*>(declaration))
563
0
      attributes.emplace_back("kind", "modifierInvocation");
564
0
    else if (dynamic_cast<ContractDefinition const*>(declaration))
565
0
      attributes.emplace_back("kind", "baseConstructorSpecifier");
566
0
  }
567
0
  setJsonNode(_node, "ModifierInvocation", std::move(attributes));
568
0
  return false;
569
0
}
570
571
bool ASTJsonExporter::visit(EventDefinition const& _node)
572
0
{
573
0
  m_inEvent = true;
574
0
  std::vector<std::pair<std::string, Json>> _attributes = {
575
0
    std::make_pair("name", _node.name()),
576
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
577
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
578
0
    std::make_pair("parameters", toJson(_node.parameterList())),
579
0
    std::make_pair("anonymous", _node.isAnonymous())
580
0
  };
581
0
  if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
582
0
      _attributes.emplace_back(
583
0
        std::make_pair(
584
0
          "eventSelector",
585
0
          toHex(u256(util::h256::Arith(util::keccak256(_node.functionType(true)->externalSignature()))))
586
0
        ));
587
588
0
  setJsonNode(_node, "EventDefinition", std::move(_attributes));
589
0
  return false;
590
0
}
591
592
bool ASTJsonExporter::visit(ErrorDefinition const& _node)
593
0
{
594
0
  std::vector<std::pair<std::string, Json>> _attributes = {
595
0
    std::make_pair("name", _node.name()),
596
0
    std::make_pair("nameLocation", sourceLocationToString(_node.nameLocation())),
597
0
    std::make_pair("documentation", _node.documentation() ? toJson(*_node.documentation()) : Json()),
598
0
    std::make_pair("parameters", toJson(_node.parameterList()))
599
0
  };
600
0
  if (m_stackState >= CompilerStack::State::AnalysisSuccessful)
601
0
    _attributes.emplace_back(std::make_pair("errorSelector", _node.functionType(true)->externalIdentifierHex()));
602
603
0
  setJsonNode(_node, "ErrorDefinition", std::move(_attributes));
604
0
  return false;
605
0
}
606
607
bool ASTJsonExporter::visit(ElementaryTypeName const& _node)
608
0
{
609
0
  std::vector<std::pair<std::string, Json>> attributes = {
610
0
    std::make_pair("name", _node.typeName().toString()),
611
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
612
0
  };
613
614
0
  if (_node.stateMutability())
615
0
    attributes.emplace_back(std::make_pair("stateMutability", stateMutabilityToString(*_node.stateMutability())));
616
617
0
  setJsonNode(_node, "ElementaryTypeName", std::move(attributes));
618
0
  return false;
619
0
}
620
621
bool ASTJsonExporter::visit(UserDefinedTypeName const& _node)
622
0
{
623
0
  setJsonNode(_node, "UserDefinedTypeName", {
624
0
    std::make_pair("pathNode", toJson(_node.pathNode())),
625
0
    std::make_pair("referencedDeclaration", idOrNull(_node.pathNode().annotation().referencedDeclaration)),
626
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
627
0
  });
628
0
  return false;
629
0
}
630
631
bool ASTJsonExporter::visit(FunctionTypeName const& _node)
632
0
{
633
0
  setJsonNode(_node, "FunctionTypeName", {
634
0
    std::make_pair("visibility", Declaration::visibilityToString(_node.visibility())),
635
0
    std::make_pair("stateMutability", stateMutabilityToString(_node.stateMutability())),
636
0
    std::make_pair("parameterTypes", toJson(*_node.parameterTypeList())),
637
0
    std::make_pair("returnParameterTypes", toJson(*_node.returnParameterTypeList())),
638
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
639
0
  });
640
0
  return false;
641
0
}
642
643
bool ASTJsonExporter::visit(Mapping const& _node)
644
0
{
645
0
  setJsonNode(_node, "Mapping", {
646
0
    std::make_pair("keyType", toJson(_node.keyType())),
647
0
    std::make_pair("keyName", _node.keyName()),
648
0
    std::make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())),
649
0
    std::make_pair("valueType", toJson(_node.valueType())),
650
0
    std::make_pair("valueName", _node.valueName()),
651
0
    std::make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())),
652
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
653
0
  });
654
0
  return false;
655
0
}
656
657
bool ASTJsonExporter::visit(ArrayTypeName const& _node)
658
0
{
659
0
  setJsonNode(_node, "ArrayTypeName", {
660
0
    std::make_pair("baseType", toJson(_node.baseType())),
661
0
    std::make_pair("length", toJsonOrNull(_node.length())),
662
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true))
663
0
  });
664
0
  return false;
665
0
}
666
667
bool ASTJsonExporter::visit(InlineAssembly const& _node)
668
0
{
669
0
  std::vector<std::pair<std::string, Json>> externalReferences;
670
671
0
  for (auto const& it: _node.annotation().externalReferences)
672
0
    if (it.first)
673
0
      externalReferences.emplace_back(std::make_pair(
674
0
        it.first->name.str(),
675
0
        inlineAssemblyIdentifierToJson(it)
676
0
      ));
677
678
0
  Json externalReferencesJson = Json::array();
679
680
0
  std::sort(externalReferences.begin(), externalReferences.end());
681
0
  for (Json& it: externalReferences | ranges::views::values)
682
0
    externalReferencesJson.emplace_back(std::move(it));
683
684
0
  auto const& evmDialect = dynamic_cast<solidity::yul::EVMDialect const&>(_node.dialect());
685
686
0
  std::vector<std::pair<std::string, Json>> attributes = {
687
0
    std::make_pair("AST", Json(yul::AsmJsonConverter(evmDialect, sourceIndexFromLocation(_node.location()))(_node.operations().root()))),
688
0
    std::make_pair("externalReferences", std::move(externalReferencesJson)),
689
0
    std::make_pair("evmVersion", evmDialect.evmVersion().name())
690
0
  };
691
692
  // TODO: Add test in test/linsolidity/ASTJSON/assembly. This requires adding support for eofVersion in ASTJSONTest
693
0
  if (evmDialect.eofVersion())
694
0
  {
695
0
    solAssert(*evmDialect.eofVersion() > 0);
696
0
    attributes.push_back(std::make_pair("eofVersion", *evmDialect.eofVersion()));
697
0
  }
698
699
0
  if (_node.flags())
700
0
  {
701
0
    Json flags = Json::array();
702
0
    for (auto const& flag: *_node.flags())
703
0
      if (flag)
704
0
        flags.emplace_back(*flag);
705
0
      else
706
0
        flags.emplace_back(Json());
707
0
    attributes.emplace_back(std::make_pair("flags", std::move(flags)));
708
0
  }
709
0
  setJsonNode(_node, "InlineAssembly", std::move(attributes));
710
711
0
  return false;
712
0
}
713
714
bool ASTJsonExporter::visit(Block const& _node)
715
0
{
716
0
  setJsonNode(_node, _node.unchecked() ? "UncheckedBlock" : "Block", {
717
0
    std::make_pair("statements", toJson(_node.statements()))
718
0
  });
719
0
  return false;
720
0
}
721
722
bool ASTJsonExporter::visit(PlaceholderStatement const& _node)
723
0
{
724
0
  setJsonNode(_node, "PlaceholderStatement", {});
725
0
  return false;
726
0
}
727
728
bool ASTJsonExporter::visit(IfStatement const& _node)
729
0
{
730
0
  setJsonNode(_node, "IfStatement", {
731
0
    std::make_pair("condition", toJson(_node.condition())),
732
0
    std::make_pair("trueBody", toJson(_node.trueStatement())),
733
0
    std::make_pair("falseBody", toJsonOrNull(_node.falseStatement()))
734
0
  });
735
0
  return false;
736
0
}
737
738
bool ASTJsonExporter::visit(TryCatchClause const& _node)
739
0
{
740
0
  setJsonNode(_node, "TryCatchClause", {
741
0
    std::make_pair("errorName", _node.errorName()),
742
0
    std::make_pair("parameters", toJsonOrNull(_node.parameters())),
743
0
    std::make_pair("block", toJson(_node.block()))
744
0
  });
745
0
  return false;
746
0
}
747
748
bool ASTJsonExporter::visit(TryStatement const& _node)
749
0
{
750
0
  setJsonNode(_node, "TryStatement", {
751
0
    std::make_pair("externalCall", toJson(_node.externalCall())),
752
0
    std::make_pair("clauses", toJson(_node.clauses()))
753
0
  });
754
0
  return false;
755
0
}
756
757
bool ASTJsonExporter::visit(WhileStatement const& _node)
758
0
{
759
0
  setJsonNode(
760
0
    _node,
761
0
    _node.isDoWhile() ? "DoWhileStatement" : "WhileStatement",
762
0
    {
763
0
      std::make_pair("condition", toJson(_node.condition())),
764
0
      std::make_pair("body", toJson(_node.body()))
765
0
    }
766
0
  );
767
0
  return false;
768
0
}
769
770
bool ASTJsonExporter::visit(ForStatement const& _node)
771
0
{
772
773
0
  std::vector<std::pair<std::string, Json>> attributes = {
774
0
    std::make_pair("initializationExpression", toJsonOrNull(_node.initializationExpression())),
775
0
    std::make_pair("condition", toJsonOrNull(_node.condition())),
776
0
    std::make_pair("loopExpression", toJsonOrNull(_node.loopExpression())),
777
0
    std::make_pair("body", toJson(_node.body()))
778
0
  };
779
780
0
  if (_node.annotation().isSimpleCounterLoop.set())
781
0
    attributes.emplace_back("isSimpleCounterLoop", *_node.annotation().isSimpleCounterLoop);
782
783
0
  setJsonNode(_node, "ForStatement", std::move(attributes));
784
0
  return false;
785
0
}
786
787
bool ASTJsonExporter::visit(Continue const& _node)
788
0
{
789
0
  setJsonNode(_node, "Continue", {});
790
0
  return false;
791
0
}
792
793
bool ASTJsonExporter::visit(Break const& _node)
794
0
{
795
0
  setJsonNode(_node, "Break", {});
796
0
  return false;
797
0
}
798
799
bool ASTJsonExporter::visit(Return const& _node)
800
0
{
801
0
  setJsonNode(_node, "Return", {
802
0
    std::make_pair("expression", toJsonOrNull(_node.expression())),
803
0
    std::make_pair("functionReturnParameters", idOrNull(_node.annotation().functionReturnParameters))
804
0
  });
805
0
  return false;
806
0
}
807
808
bool ASTJsonExporter::visit(Throw const& _node)
809
0
{
810
0
  setJsonNode(_node, "Throw", {});
811
0
  return false;
812
0
}
813
814
bool ASTJsonExporter::visit(EmitStatement const& _node)
815
0
{
816
0
  setJsonNode(_node, "EmitStatement", {
817
0
    std::make_pair("eventCall", toJson(_node.eventCall()))
818
0
  });
819
0
  return false;
820
0
}
821
822
bool ASTJsonExporter::visit(RevertStatement const& _node)
823
0
{
824
0
  setJsonNode(_node, "RevertStatement", {
825
0
    std::make_pair("errorCall", toJson(_node.errorCall()))
826
0
  });
827
0
  return false;
828
0
}
829
830
bool ASTJsonExporter::visit(VariableDeclarationStatement const& _node)
831
0
{
832
0
  Json varDecs = Json::array();
833
0
  for (auto const& v: _node.declarations())
834
0
    appendMove(varDecs, idOrNull(v.get()));
835
0
  setJsonNode(_node, "VariableDeclarationStatement", {
836
0
    std::make_pair("assignments", std::move(varDecs)),
837
0
    std::make_pair("declarations", toJson(_node.declarations())),
838
0
    std::make_pair("initialValue", toJsonOrNull(_node.initialValue()))
839
0
  });
840
0
  return false;
841
0
}
842
843
bool ASTJsonExporter::visit(ExpressionStatement const& _node)
844
0
{
845
0
  setJsonNode(_node, "ExpressionStatement", {
846
0
    std::make_pair("expression", toJson(_node.expression()))
847
0
  });
848
0
  return false;
849
0
}
850
851
bool ASTJsonExporter::visit(Conditional const& _node)
852
0
{
853
0
  std::vector<std::pair<std::string, Json>> attributes = {
854
0
    std::make_pair("condition", toJson(_node.condition())),
855
0
    std::make_pair("trueExpression", toJson(_node.trueExpression())),
856
0
    std::make_pair("falseExpression", toJson(_node.falseExpression()))
857
0
  };
858
0
  appendExpressionAttributes(attributes, _node.annotation());
859
0
  setJsonNode(_node, "Conditional", std::move(attributes));
860
0
  return false;
861
0
}
862
863
bool ASTJsonExporter::visit(Assignment const& _node)
864
0
{
865
0
  std::vector<std::pair<std::string, Json>> attributes = {
866
0
    std::make_pair("operator", TokenTraits::toString(_node.assignmentOperator())),
867
0
    std::make_pair("leftHandSide", toJson(_node.leftHandSide())),
868
0
    std::make_pair("rightHandSide", toJson(_node.rightHandSide()))
869
0
  };
870
0
  appendExpressionAttributes(attributes, _node.annotation());
871
0
  setJsonNode(_node, "Assignment", std::move(attributes));
872
0
  return false;
873
0
}
874
875
bool ASTJsonExporter::visit(TupleExpression const& _node)
876
0
{
877
0
  std::vector<std::pair<std::string, Json>> attributes = {
878
0
    std::make_pair("isInlineArray", Json(_node.isInlineArray())),
879
0
    std::make_pair("components", toJson(_node.components())),
880
0
  };
881
0
  appendExpressionAttributes(attributes, _node.annotation());
882
0
  setJsonNode(_node, "TupleExpression", std::move(attributes));
883
0
  return false;
884
0
}
885
886
bool ASTJsonExporter::visit(UnaryOperation const& _node)
887
0
{
888
0
  std::vector<std::pair<std::string, Json>> attributes = {
889
0
    std::make_pair("prefix", _node.isPrefixOperation()),
890
0
    std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
891
0
    std::make_pair("subExpression", toJson(_node.subExpression()))
892
0
  };
893
  // NOTE: This annotation is guaranteed to be set but only if we didn't stop at the parsing stage.
894
0
  if (_node.annotation().userDefinedFunction.set() && *_node.annotation().userDefinedFunction != nullptr)
895
0
    attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction));
896
0
  appendExpressionAttributes(attributes, _node.annotation());
897
0
  setJsonNode(_node, "UnaryOperation", std::move(attributes));
898
0
  return false;
899
0
}
900
901
bool ASTJsonExporter::visit(BinaryOperation const& _node)
902
0
{
903
0
  std::vector<std::pair<std::string, Json>> attributes = {
904
0
    std::make_pair("operator", TokenTraits::toString(_node.getOperator())),
905
0
    std::make_pair("leftExpression", toJson(_node.leftExpression())),
906
0
    std::make_pair("rightExpression", toJson(_node.rightExpression())),
907
0
    std::make_pair("commonType", typePointerToJson(_node.annotation().commonType)),
908
0
  };
909
  // NOTE: This annotation is guaranteed to be set but only if we didn't stop at the parsing stage.
910
0
  if (_node.annotation().userDefinedFunction.set() && *_node.annotation().userDefinedFunction != nullptr)
911
0
    attributes.emplace_back("function", nodeId(**_node.annotation().userDefinedFunction));
912
0
  appendExpressionAttributes(attributes, _node.annotation());
913
0
  setJsonNode(_node, "BinaryOperation", std::move(attributes));
914
0
  return false;
915
0
}
916
917
bool ASTJsonExporter::visit(FunctionCall const& _node)
918
0
{
919
0
  Json names = Json::array();
920
0
  for (auto const& name: _node.names())
921
0
    names.push_back(Json(*name));
922
0
  std::vector<std::pair<std::string, Json>> attributes = {
923
0
    std::make_pair("expression", toJson(_node.expression())),
924
0
    std::make_pair("names", std::move(names)),
925
0
    std::make_pair("nameLocations", sourceLocationsToJson(_node.nameLocations())),
926
0
    std::make_pair("arguments", toJson(_node.arguments())),
927
0
    std::make_pair("tryCall", _node.annotation().tryCall)
928
0
  };
929
930
0
  if (_node.annotation().kind.set())
931
0
  {
932
0
    FunctionCallKind nodeKind = *_node.annotation().kind;
933
0
    attributes.emplace_back("kind", functionCallKind(nodeKind));
934
0
  }
935
936
0
  appendExpressionAttributes(attributes, _node.annotation());
937
0
  setJsonNode(_node, "FunctionCall", std::move(attributes));
938
0
  return false;
939
0
}
940
941
bool ASTJsonExporter::visit(FunctionCallOptions const& _node)
942
0
{
943
0
  Json names = Json::array();
944
0
  for (auto const& name: _node.names())
945
0
    names.emplace_back(Json(*name));
946
947
0
  std::vector<std::pair<std::string, Json>> attributes = {
948
0
    std::make_pair("expression", toJson(_node.expression())),
949
0
    std::make_pair("names", std::move(names)),
950
0
    std::make_pair("options", toJson(_node.options())),
951
0
  };
952
0
  appendExpressionAttributes(attributes, _node.annotation());
953
954
0
  setJsonNode(_node, "FunctionCallOptions", std::move(attributes));
955
0
  return false;
956
0
}
957
958
bool ASTJsonExporter::visit(NewExpression const& _node)
959
0
{
960
0
  std::vector<std::pair<std::string, Json>> attributes = {
961
0
    std::make_pair("typeName", toJson(_node.typeName()))
962
0
  };
963
0
  appendExpressionAttributes(attributes, _node.annotation());
964
0
  setJsonNode(_node, "NewExpression", std::move(attributes));
965
0
  return false;
966
0
}
967
968
bool ASTJsonExporter::visit(MemberAccess const& _node)
969
0
{
970
0
  std::vector<std::pair<std::string, Json>> attributes = {
971
0
    std::make_pair("memberName", _node.memberName()),
972
0
    std::make_pair("memberLocation", Json(sourceLocationToString(_node.memberLocation()))),
973
0
    std::make_pair("expression", toJson(_node.expression())),
974
0
    std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
975
0
  };
976
0
  appendExpressionAttributes(attributes, _node.annotation());
977
0
  setJsonNode(_node, "MemberAccess", std::move(attributes));
978
0
  return false;
979
0
}
980
981
bool ASTJsonExporter::visit(IndexAccess const& _node)
982
0
{
983
0
  std::vector<std::pair<std::string, Json>> attributes = {
984
0
    std::make_pair("baseExpression", toJson(_node.baseExpression())),
985
0
    std::make_pair("indexExpression", toJsonOrNull(_node.indexExpression())),
986
0
  };
987
0
  appendExpressionAttributes(attributes, _node.annotation());
988
0
  setJsonNode(_node, "IndexAccess", std::move(attributes));
989
0
  return false;
990
0
}
991
992
bool ASTJsonExporter::visit(IndexRangeAccess const& _node)
993
0
{
994
0
  std::vector<std::pair<std::string, Json>> attributes = {
995
0
    std::make_pair("baseExpression", toJson(_node.baseExpression())),
996
0
    std::make_pair("startExpression", toJsonOrNull(_node.startExpression())),
997
0
    std::make_pair("endExpression", toJsonOrNull(_node.endExpression())),
998
0
  };
999
0
  appendExpressionAttributes(attributes, _node.annotation());
1000
0
  setJsonNode(_node, "IndexRangeAccess", std::move(attributes));
1001
0
  return false;
1002
0
}
1003
1004
bool ASTJsonExporter::visit(Identifier const& _node)
1005
0
{
1006
0
  Json overloads = Json::array();
1007
0
  for (auto const& dec: _node.annotation().overloadedDeclarations)
1008
0
    overloads.emplace_back(nodeId(*dec));
1009
0
  setJsonNode(_node, "Identifier", {
1010
0
    std::make_pair("name", _node.name()),
1011
0
    std::make_pair("referencedDeclaration", idOrNull(_node.annotation().referencedDeclaration)),
1012
0
    std::make_pair("overloadedDeclarations", overloads),
1013
0
    std::make_pair("typeDescriptions", typePointerToJson(_node.annotation().type)),
1014
0
    std::make_pair("argumentTypes", typePointerToJson(_node.annotation().arguments))
1015
0
  });
1016
0
  return false;
1017
0
}
1018
1019
bool ASTJsonExporter::visit(ElementaryTypeNameExpression const& _node)
1020
0
{
1021
0
  std::vector<std::pair<std::string, Json>> attributes = {
1022
0
    std::make_pair("typeName", toJson(_node.type()))
1023
0
  };
1024
0
  appendExpressionAttributes(attributes, _node.annotation());
1025
0
  setJsonNode(_node, "ElementaryTypeNameExpression", std::move(attributes));
1026
0
  return false;
1027
0
}
1028
1029
bool ASTJsonExporter::visit(Literal const& _node)
1030
0
{
1031
0
  Json value = _node.value();
1032
0
  if (!util::validateUTF8(_node.value()))
1033
0
    value = Json();
1034
0
  Token subdenomination = Token(_node.subDenomination());
1035
0
  std::vector<std::pair<std::string, Json>> attributes = {
1036
0
    std::make_pair("kind", literalTokenKind(_node.token())),
1037
0
    std::make_pair("value", value),
1038
0
    std::make_pair("hexValue", util::toHex(util::asBytes(_node.value()))),
1039
0
    std::make_pair(
1040
0
      "subdenomination",
1041
0
      subdenomination == Token::Illegal ?
1042
0
      Json() :
1043
0
      Json(TokenTraits::toString(subdenomination))
1044
0
    )
1045
0
  };
1046
0
  appendExpressionAttributes(attributes, _node.annotation());
1047
0
  setJsonNode(_node, "Literal", std::move(attributes));
1048
0
  return false;
1049
0
}
1050
1051
bool ASTJsonExporter::visit(StructuredDocumentation const& _node)
1052
0
{
1053
0
  Json text = *_node.text();
1054
0
  std::vector<std::pair<std::string, Json>> attributes = {
1055
0
    std::make_pair("text", text)
1056
0
  };
1057
0
  setJsonNode(_node, "StructuredDocumentation", std::move(attributes));
1058
0
  return false;
1059
0
}
1060
1061
void ASTJsonExporter::endVisit(EventDefinition const&)
1062
0
{
1063
0
  m_inEvent = false;
1064
0
}
1065
1066
bool ASTJsonExporter::visitNode(ASTNode const& _node)
1067
0
{
1068
0
  solAssert(false, _node.experimentalSolidityOnly() ?
1069
0
    "Attempt to export an AST of experimental solidity." :
1070
0
    "Attempt to export an AST that contains unexpected nodes."
1071
0
  );
1072
0
  return false;
1073
0
}
1074
1075
std::string ASTJsonExporter::location(VariableDeclaration::Location _location)
1076
0
{
1077
0
  switch (_location)
1078
0
  {
1079
0
  case VariableDeclaration::Location::Unspecified:
1080
0
    return "default";
1081
0
  case VariableDeclaration::Location::Storage:
1082
0
    return "storage";
1083
0
  case VariableDeclaration::Location::Memory:
1084
0
    return "memory";
1085
0
  case VariableDeclaration::Location::CallData:
1086
0
    return "calldata";
1087
0
  case VariableDeclaration::Location::Transient:
1088
0
    return "transient";
1089
0
  }
1090
  // To make the compiler happy
1091
0
  return {};
1092
0
}
1093
1094
std::string ASTJsonExporter::contractKind(ContractKind _kind)
1095
0
{
1096
0
  switch (_kind)
1097
0
  {
1098
0
  case ContractKind::Interface:
1099
0
    return "interface";
1100
0
  case ContractKind::Contract:
1101
0
    return "contract";
1102
0
  case ContractKind::Library:
1103
0
    return "library";
1104
0
  }
1105
1106
  // To make the compiler happy
1107
0
  return {};
1108
0
}
1109
1110
std::string ASTJsonExporter::functionCallKind(FunctionCallKind _kind)
1111
0
{
1112
0
  switch (_kind)
1113
0
  {
1114
0
  case FunctionCallKind::FunctionCall:
1115
0
    return "functionCall";
1116
0
  case FunctionCallKind::TypeConversion:
1117
0
    return "typeConversion";
1118
0
  case FunctionCallKind::StructConstructorCall:
1119
0
    return "structConstructorCall";
1120
0
  default:
1121
0
    solAssert(false, "Unknown kind of function call.");
1122
0
  }
1123
0
}
1124
1125
std::string ASTJsonExporter::literalTokenKind(Token _token)
1126
0
{
1127
0
  switch (_token)
1128
0
  {
1129
0
  case Token::Number:
1130
0
    return "number";
1131
0
  case Token::StringLiteral:
1132
0
    return "string";
1133
0
  case Token::UnicodeStringLiteral:
1134
0
    return "unicodeString";
1135
0
  case Token::HexStringLiteral:
1136
0
    return "hexString";
1137
0
  case Token::TrueLiteral:
1138
0
  case Token::FalseLiteral:
1139
0
    return "bool";
1140
0
  default:
1141
0
    solAssert(false, "Unknown kind of literal token.");
1142
0
  }
1143
0
}
1144
1145
std::string ASTJsonExporter::type(Expression const& _expression)
1146
0
{
1147
0
  return _expression.annotation().type ? _expression.annotation().type->toString() : "Unknown";
1148
0
}
1149
1150
std::string ASTJsonExporter::type(VariableDeclaration const& _varDecl)
1151
0
{
1152
0
  return _varDecl.annotation().type ? _varDecl.annotation().type->toString() : "Unknown";
1153
0
}
1154
1155
}