diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 3ba28a439..06575beec 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -1428,28 +1428,36 @@ public: SourceLocation const& _location, ASTPointer _keyType, ASTPointer _keyName, + SourceLocation _keyNameLocation, ASTPointer _valueType, - ASTPointer _valueName + ASTPointer _valueName, + SourceLocation _valueNameLocation ): TypeName(_id, _location), m_keyType(std::move(_keyType)), m_keyName(std::move(_keyName)), + m_keyNameLocation(std::move(_keyNameLocation)), m_valueType(std::move(_valueType)), - m_valueName(std::move(_valueName)) + m_valueName(std::move(_valueName)), + m_valueNameLocation(std::move(_valueNameLocation)) {} void accept(ASTVisitor& _visitor) override; void accept(ASTConstVisitor& _visitor) const override; TypeName const& keyType() const { return *m_keyType; } ASTString keyName() const { return *m_keyName; } + SourceLocation keyNameLocation() const { return m_keyNameLocation; } TypeName const& valueType() const { return *m_valueType; } ASTString valueName() const { return *m_valueName; } + SourceLocation valueNameLocation() const { return m_valueNameLocation; } private: ASTPointer m_keyType; ASTPointer m_keyName; + SourceLocation m_keyNameLocation; ASTPointer m_valueType; ASTPointer m_valueName; + SourceLocation m_valueNameLocation; }; /** diff --git a/libsolidity/ast/ASTJsonExporter.cpp b/libsolidity/ast/ASTJsonExporter.cpp index 7ae528fcd..8b46684bc 100644 --- a/libsolidity/ast/ASTJsonExporter.cpp +++ b/libsolidity/ast/ASTJsonExporter.cpp @@ -599,8 +599,10 @@ bool ASTJsonExporter::visit(Mapping const& _node) setJsonNode(_node, "Mapping", { make_pair("keyType", toJson(_node.keyType())), make_pair("keyName", _node.keyName()), + make_pair("keyNameLocation", sourceLocationToString(_node.keyNameLocation())), make_pair("valueType", toJson(_node.valueType())), make_pair("valueName", _node.valueName()), + make_pair("valueNameLocation", sourceLocationToString(_node.valueNameLocation())), make_pair("typeDescriptions", typePointerToJson(_node.annotation().type, true)) }); return false; diff --git a/libsolidity/ast/ASTJsonImporter.cpp b/libsolidity/ast/ASTJsonImporter.cpp index 22b53aa47..079704946 100644 --- a/libsolidity/ast/ASTJsonImporter.cpp +++ b/libsolidity/ast/ASTJsonImporter.cpp @@ -116,6 +116,20 @@ SourceLocation ASTJsonImporter::createNameSourceLocation(Json::Value const& _nod return solidity::langutil::parseSourceLocation(_node["nameLocation"].asString(), m_sourceNames); } +SourceLocation ASTJsonImporter::createKeyNameSourceLocation(Json::Value const& _node) +{ + astAssert(member(_node, "keyNameLocation").isString(), "'keyNameLocation' must be a string"); + + return solidity::langutil::parseSourceLocation(_node["keyNameLocation"].asString(), m_sourceNames); +} + +SourceLocation ASTJsonImporter::createValueNameSourceLocation(Json::Value const& _node) +{ + astAssert(member(_node, "valueNameLocation").isString(), "'valueNameLocation' must be a string"); + + return solidity::langutil::parseSourceLocation(_node["valueNameLocation"].asString(), m_sourceNames); +} + template ASTPointer ASTJsonImporter::convertJsonToASTNode(Json::Value const& _node) { @@ -649,8 +663,10 @@ ASTPointer ASTJsonImporter::createMapping(Json::Value const& _node) _node, convertJsonToASTNode(member(_node, "keyType")), memberAsASTString(_node, "keyName"), + createKeyNameSourceLocation(_node), convertJsonToASTNode(member(_node, "valueType")), - memberAsASTString(_node, "valueName") + memberAsASTString(_node, "valueName"), + createValueNameSourceLocation(_node) ); } diff --git a/libsolidity/ast/ASTJsonImporter.h b/libsolidity/ast/ASTJsonImporter.h index 1216d29b1..b9a4d4950 100644 --- a/libsolidity/ast/ASTJsonImporter.h +++ b/libsolidity/ast/ASTJsonImporter.h @@ -69,6 +69,10 @@ private: ASTPointer convertJsonToASTNode(Json::Value const& _node); langutil::SourceLocation createNameSourceLocation(Json::Value const& _node); + /// @returns source location of a mapping key name + langutil::SourceLocation createKeyNameSourceLocation(Json::Value const& _node); + /// @returns source location of a mapping value name + langutil::SourceLocation createValueNameSourceLocation(Json::Value const& _node); /// \defgroup nodeCreators JSON to AST-Nodes ///@{ diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index e81f0713f..fee21e518 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1187,21 +1187,19 @@ ASTPointer Parser::parseMapping() } else fatalParserError(1005_error, "Expected elementary type name or identifier for mapping key type"); - ASTPointer keyName; + ASTPointer keyName = make_shared(""); + SourceLocation keyNameLocation{}; if (m_scanner->currentToken() == Token::Identifier) - keyName = getLiteralAndAdvance(); - else - keyName = make_shared(""); + tie(keyName, keyNameLocation) = expectIdentifierWithLocation(); expectToken(Token::DoubleArrow); ASTPointer valueType = parseTypeName(); - ASTPointer valueName; + ASTPointer valueName = make_shared(""); + SourceLocation valueNameLocation{}; if (m_scanner->currentToken() == Token::Identifier) - valueName = getLiteralAndAdvance(); - else - valueName = make_shared(""); + tie(valueName, valueNameLocation) = expectIdentifierWithLocation(); nodeFactory.markEndPosition(); expectToken(Token::RParen); - return nodeFactory.createNode(keyType, keyName, valueType, valueName); + return nodeFactory.createNode(keyType, keyName, keyNameLocation, valueType, valueName, valueNameLocation); } ASTPointer Parser::parseParameterList( diff --git a/test/libsolidity/ASTJSON/address_payable.json b/test/libsolidity/ASTJSON/address_payable.json index bf56f067f..83ba2c6d7 100644 --- a/test/libsolidity/ASTJSON/address_payable.json +++ b/test/libsolidity/ASTJSON/address_payable.json @@ -49,6 +49,7 @@ { "id": 3, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 1, @@ -69,6 +70,7 @@ "typeString": "mapping(address => address payable)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/address_payable_parseOnly.json b/test/libsolidity/ASTJSON/address_payable_parseOnly.json index 6b72b6fb3..9d095dc68 100644 --- a/test/libsolidity/ASTJSON/address_payable_parseOnly.json +++ b/test/libsolidity/ASTJSON/address_payable_parseOnly.json @@ -30,6 +30,7 @@ { "id": 3, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 1, @@ -42,6 +43,7 @@ "src": "17:35:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 2, diff --git a/test/libsolidity/ASTJSON/mappings.json b/test/libsolidity/ASTJSON/mappings.json index f63f6689f..0bf816eb4 100644 --- a/test/libsolidity/ASTJSON/mappings.json +++ b/test/libsolidity/ASTJSON/mappings.json @@ -4,10 +4,10 @@ { "C": [ - 19 + 23 ] }, - "id": 20, + "id": 24, "nodeType": "SourceUnit", "nodes": [ @@ -18,10 +18,10 @@ "contractDependencies": [], "contractKind": "contract", "fullyImplemented": true, - "id": 19, + "id": 23, "linearizedBaseContracts": [ - 19 + 23 ], "name": "C", "nameLocation": "9:1:1", @@ -67,19 +67,20 @@ "name": "a", "nameLocation": "59:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "40:20:1", "stateVariable": true, "storageLocation": "default", "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$", + "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, "typeName": { "id": 8, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 6, @@ -93,14 +94,14 @@ "48:1:1" ], "nodeType": "IdentifierPath", - "referencedDeclaration": 19, + "referencedDeclaration": 23, "src": "48:1:1" }, - "referencedDeclaration": 19, + "referencedDeclaration": 23, "src": "48:1:1", "typeDescriptions": { - "typeIdentifier": "t_contract$_C_$19", + "typeIdentifier": "t_contract$_C_$23", "typeString": "contract C" } }, @@ -108,10 +109,11 @@ "src": "40:18:1", "typeDescriptions": { - "typeIdentifier": "t_mapping$_t_contract$_C_$19_$_t_bool_$", + "typeIdentifier": "t_mapping$_t_contract$_C_$23_$_t_bool_$", "typeString": "mapping(contract C => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 7, @@ -134,7 +136,7 @@ "name": "b", "nameLocation": "91:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "66:26:1", "stateVariable": true, "storageLocation": "default", @@ -147,6 +149,7 @@ { "id": 12, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 10, @@ -167,6 +170,7 @@ "typeString": "mapping(address => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 11, @@ -189,7 +193,7 @@ "name": "c", "nameLocation": "117:1:1", "nodeType": "VariableDeclaration", - "scope": 19, + "scope": 23, "src": "98:20:1", "stateVariable": true, "storageLocation": "default", @@ -202,6 +206,7 @@ { "id": 17, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 15, @@ -234,6 +239,7 @@ "typeString": "mapping(enum C.E => bool)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 16, @@ -248,12 +254,69 @@ } }, "visibility": "internal" + }, + { + "constant": false, + "id": 22, + "mutability": "mutable", + "name": "d", + "nameLocation": "169:1:1", + "nodeType": "VariableDeclaration", + "scope": 23, + "src": "124:46:1", + "stateVariable": true, + "storageLocation": "default", + "typeDescriptions": + { + "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", + "typeString": "mapping(address => uint256)" + }, + "typeName": + { + "id": 21, + "keyName": "keyAddress", + "keyNameLocation": "140:10:1", + "keyType": + { + "id": 19, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "132:7:1", + "typeDescriptions": + { + "typeIdentifier": "t_address", + "typeString": "address" + } + }, + "nodeType": "Mapping", + "src": "124:44:1", + "typeDescriptions": + { + "typeIdentifier": "t_mapping$_t_address_$_t_uint256_$", + "typeString": "mapping(address => uint256)" + }, + "valueName": "value", + "valueNameLocation": "162:5:1", + "valueType": + { + "id": 20, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "154:7:1", + "typeDescriptions": + { + "typeIdentifier": "t_uint256", + "typeString": "uint256" + } + } + }, + "visibility": "internal" } ], - "scope": 20, - "src": "0:121:1", + "scope": 24, + "src": "0:173:1", "usedErrors": [] } ], - "src": "0:122:1" + "src": "0:174:1" } diff --git a/test/libsolidity/ASTJSON/mappings.sol b/test/libsolidity/ASTJSON/mappings.sol index 794396a7d..05912d21f 100644 --- a/test/libsolidity/ASTJSON/mappings.sol +++ b/test/libsolidity/ASTJSON/mappings.sol @@ -3,6 +3,7 @@ contract C { mapping(C => bool) a; mapping(address => bool) b; mapping(E => bool) c; + mapping(address keyAddress => uint256 value) d; } // ---- diff --git a/test/libsolidity/ASTJSON/mappings_parseOnly.json b/test/libsolidity/ASTJSON/mappings_parseOnly.json index 247114849..9690f7c9e 100644 --- a/test/libsolidity/ASTJSON/mappings_parseOnly.json +++ b/test/libsolidity/ASTJSON/mappings_parseOnly.json @@ -1,6 +1,6 @@ { "absolutePath": "a", - "id": 20, + "id": 24, "nodeType": "SourceUnit", "nodes": [ @@ -9,7 +9,7 @@ "baseContracts": [], "contractDependencies": [], "contractKind": "contract", - "id": 19, + "id": 23, "name": "C", "nameLocation": "9:1:1", "nodeType": "ContractDefinition", @@ -61,6 +61,7 @@ { "id": 8, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 6, @@ -83,6 +84,7 @@ "src": "40:18:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 7, @@ -109,6 +111,7 @@ { "id": 12, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 10, @@ -121,6 +124,7 @@ "src": "66:24:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 11, @@ -147,6 +151,7 @@ { "id": 17, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 15, @@ -169,6 +174,7 @@ "src": "98:18:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 16, @@ -179,11 +185,51 @@ } }, "visibility": "internal" + }, + { + "constant": false, + "id": 22, + "mutability": "mutable", + "name": "d", + "nameLocation": "169:1:1", + "nodeType": "VariableDeclaration", + "src": "124:46:1", + "stateVariable": false, + "storageLocation": "default", + "typeDescriptions": {}, + "typeName": + { + "id": 21, + "keyName": "keyAddress", + "keyNameLocation": "140:10:1", + "keyType": + { + "id": 19, + "name": "address", + "nodeType": "ElementaryTypeName", + "src": "132:7:1", + "typeDescriptions": {} + }, + "nodeType": "Mapping", + "src": "124:44:1", + "typeDescriptions": {}, + "valueName": "value", + "valueNameLocation": "162:5:1", + "valueType": + { + "id": 20, + "name": "uint256", + "nodeType": "ElementaryTypeName", + "src": "154:7:1", + "typeDescriptions": {} + } + }, + "visibility": "internal" } ], - "src": "0:121:1", + "src": "0:173:1", "usedErrors": [] } ], - "src": "0:122:1" + "src": "0:174:1" } diff --git a/test/libsolidity/ASTJSON/userDefinedValueType.json b/test/libsolidity/ASTJSON/userDefinedValueType.json index 743716548..eb4450946 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType.json @@ -288,6 +288,7 @@ { "id": 25, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 22, @@ -320,6 +321,7 @@ "typeString": "mapping(C.MyAddress => C.MyUInt)" }, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 24, diff --git a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json index 5e263eaea..0dc95e13f 100644 --- a/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json +++ b/test/libsolidity/ASTJSON/userDefinedValueType_parseOnly.json @@ -214,6 +214,7 @@ { "id": 25, "keyName": "", + "keyNameLocation": "-1:-1:-1", "keyType": { "id": 22, @@ -236,6 +237,7 @@ "src": "169:28:1", "typeDescriptions": {}, "valueName": "", + "valueNameLocation": "-1:-1:-1", "valueType": { "id": 24,