Skip to content

Commit

Permalink
[WA-37]: Append method id to duplicate function names (#9)
Browse files Browse the repository at this point in the history
  • Loading branch information
zweigraf authored Oct 23, 2017
1 parent dbdd502 commit 6b4ae07
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 16 deletions.
49 changes: 33 additions & 16 deletions Sources/BivrostKit/Generating/ContractTemplateModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,39 @@ struct ContractTemplateModel {
init(contract: Contract) {
name = contract.name.asTypeName

functions = contract.elements.flatMap { element -> ContractTemplateModel.Function? in
guard case .function(let object) = element else { return nil }

let functionName = object.name.asTypeName
let functionMethodId = object.methodId

let inputString = tupleString(for: object.inputs)
let outputString = tupleString(for: object.outputs)

let encodeArgumentsString = encodeArguments(for: object.inputs)
let decodeReturnTypesArray = decodeTypes(for: object.outputs)
let decodeReturnReturnValueString = decodeReturnReturnValue(for: decodeReturnTypesArray)
let decodeArgumentsTypesArray = decodeTypes(for: object.inputs)
let decodeArgumentsReturnValueString = decodeArgumentsReturnValue(for: decodeArgumentsTypesArray)

return ContractTemplateModel.Function(name: functionName, methodId: functionMethodId, input: inputString, output: outputString, encodeArguments: encodeArgumentsString, decodeReturnReturnValue: decodeReturnReturnValueString, decodeReturnTypes: decodeReturnTypesArray, decodeArgumentsReturnValue: decodeArgumentsReturnValueString, decodeArgumentsTypes: decodeArgumentsTypesArray)
// In code generation function names are used for struct names.
// This means they have to be unique, so filter for duplicate entries
// and append the method id on all of them (group by name, mark non-uniques
// and treat them accordingly)
functions = contract.elements
.flatMap {
guard case .function(let object) = $0 else { return nil }
return object
}
.group(by: { $0.name })
.flatMap { entry -> [(Contract.Element.Function, Bool)] in
// flatMap grouped array (dictionary) into an array of
// (object, useMethodId) tuples
return entry.value.map { ($0, entry.value.count > 1) }
}
.flatMap { pair -> ContractTemplateModel.Function? in
let object = pair.0
let shouldAppendMethodId = pair.1

let functionMethodId = object.methodId
let functionName = object.name.asTypeName
let preparedFunctionName = shouldAppendMethodId ? "\(functionName)_\(object.methodId)" : functionName

let inputString = tupleString(for: object.inputs)
let outputString = tupleString(for: object.outputs)

let encodeArgumentsString = encodeArguments(for: object.inputs)
let decodeReturnTypesArray = decodeTypes(for: object.outputs)
let decodeReturnReturnValueString = decodeReturnReturnValue(for: decodeReturnTypesArray)
let decodeArgumentsTypesArray = decodeTypes(for: object.inputs)
let decodeArgumentsReturnValueString = decodeArgumentsReturnValue(for: decodeArgumentsTypesArray)

return ContractTemplateModel.Function(name: preparedFunctionName, methodId: functionMethodId, input: inputString, output: outputString, encodeArguments: encodeArgumentsString, decodeReturnReturnValue: decodeReturnReturnValueString, decodeReturnTypes: decodeReturnTypesArray, decodeArgumentsReturnValue: decodeArgumentsReturnValueString, decodeArgumentsTypes: decodeArgumentsTypesArray)
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions Sources/BivrostKit/Generating/SequenceExtension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// SequenceExtension.swift
// BivrostKit
//
// Created by Luis Reisewitz on 23.10.17.
//

// From https://stackoverflow.com/a/31220067/972993

public extension Sequence {
func group<U: Hashable>(by key: (Iterator.Element) -> U) -> [U:[Iterator.Element]] {
var categories: [U: [Iterator.Element]] = [:]
for element in self {
let key = key(element)
if case nil = categories[key]?.append(element) {
categories[key] = [element]
}
}
return categories
}
}
43 changes: 43 additions & 0 deletions Tests/BivrostKitTests/Assets.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,49 @@
//

struct Assets {
static let duplicateMethodJson = """
{
"contract_name": "DuplicateMethod",
"abi": [
{
"constant": true,
"inputs": [],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
},
{
"constant": true,
"inputs": [
{
"name": "spender",
"type": "address"
},
{
"name": "value",
"type": "uint256"
}
],
"name": "totalSupply",
"outputs": [
{
"name": "",
"type": "uint256"
}
],
"payable": false,
"type": "function"
}
]
}
"""
static let multiSigWalletJson = """
{
"contract_name": "MultiSigWalletWithDailyLimit",
Expand Down
42 changes: 42 additions & 0 deletions Tests/BivrostKitTests/ContractTemplateModelSpec.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// ContractTemplateModelSpec.swift
// BivrostKitTests
//
// Created by Luis Reisewitz on 23.10.17.
// Copyright © 2017 Gnosis. All rights reserved.
//


import Foundation
import Quick
import Nimble
@testable import BivrostKit

class ContractTemplateModelSpec: QuickSpec {
override func spec() {
describe("ContractTemplateModel") {
it("should append method ids to generated function names in case of duplicates") {
let json = jsonDict(from: Assets.duplicateMethodJson)
let contract = try! ContractParser.parseContract(from: json)
let model = ContractTemplateModel(contract: contract)
model.functions.forEach {
expect($0.name).to(contain($0.methodId))
}
}

it("should not append method ids to generated function names in case of no duplicates") {
let json = jsonDict(from: Assets.standardTokenJson)
let contract = try! ContractParser.parseContract(from: json)
let model = ContractTemplateModel(contract: contract)
model.functions.forEach {
expect($0.name).toNot(contain($0.methodId))
}
}
}
}

}

fileprivate func jsonDict(from jsonString: String) -> [String: Any] {
return try! JSONSerialization.jsonObject(with: jsonString.data(using: .utf8)!, options: []) as! [String: Any]
}

0 comments on commit 6b4ae07

Please sign in to comment.