Coverage Report

Created: 2022-08-24 06:55

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