/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 | | } |