Skip to content
This repository was archived by the owner on May 23, 2023. It is now read-only.

better solidity_names #360

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ before_install:
- sudo add-apt-repository -y ppa:ethereum/ethereum
- sudo apt-get update
- sudo apt-get install -y solc
- solc --version
env:
matrix:
- TOX_ENV=py27
Expand Down
58 changes: 10 additions & 48 deletions ethereum/_solidity.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,57 +96,19 @@ def compiler_version():
return match.group(1)


def solidity_names(code): # pylint: disable=too-many-branches
""" Return the library and contract names in order of appearence. """
names = []
in_string = None
backslash = False
comment = None

# "parse" the code by hand to handle the corner cases:
# - the contract or library can be inside a comment or string
# - multiline comments
# - the contract and library keywords could not be at the start of the line
for pos, char in enumerate(code):
if in_string:
if not backslash and in_string == char:
in_string = None
backslash = False

if char == '\\': # pylint: disable=simplifiable-if-statement
backslash = True
else:
backslash = False

elif comment == '//':
if char in ('\n', '\r'):
comment = None

elif comment == '/*':
if char == '*' and code[pos + 1] == '/':
comment = None

else:
if char == '"' or char == "'":
in_string = char
def remove_comments(string):
string = re.sub(re.compile("/\*.*?\*/",re.DOTALL ) ,"" ,string) # remove all occurance streamed comments (/*COMMENT */) from string
string = re.sub(re.compile("//.*?\n" ) ,"" ,string) # remove all occurance singleline comments (//COMMENT\n ) from string
return string

if char == '/':
if code[pos + 1] == '/':
comment = '//'
if code[pos + 1] == '*':
comment = '/*'

if char == 'c' and code[pos: pos + 8] == 'contract':
result = re.match('^contract[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])

if result:
names.append(('contract', result.groups()[0]))

if char == 'l' and code[pos: pos + 7] == 'library':
result = re.match('^library[^_$a-zA-Z]+([_$a-zA-Z][_$a-zA-Z0-9]*)', code[pos:])
def solidity_names(code):
""" Return the library and contract names in order of appearence. """
names = []
cleancode = remove_comments(code)

if result:
names.append(('library', result.groups()[0]))
for m in re.findall(r'^\s*?(contract|library)\s+?(\S*?)\s+?', cleancode, re.MULTILINE):
names.append((m[0], m[1]))

return names

Expand Down
50 changes: 50 additions & 0 deletions ethereum/tests/test_solidity.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,56 @@
CONTRACTS_DIR = path.join(path.dirname(__file__), 'contracts')


def test_solidity_names():
# test simple extracting names
code = '''
contract test1 {}
contract test2 {}
'''
assert _solidity.solidity_names(code) == [('contract', 'test1'), ('contract', 'test2')]

# test with odd comment
code = '''
contract test1
// odd comment here
/* more odd comments */
{}
'''
assert _solidity.solidity_names(code) == [('contract', 'test1')]

# test with contract in comment
code = '''
contract test1 {}
//contract test2 {}
/*contract test3 {}*/
/*
contract test4 {}
*/
'''
assert _solidity.solidity_names(code) == [('contract', 'test1')]

# test with a var named 'subcontract'
code = '''
contract test1 {
_subcontract = new subcontract();
}
'''
assert _solidity.solidity_names(code) == [('contract', 'test1')]

# test with a contract named subcontract
code = '''
contract subcontract {}
'''
assert _solidity.solidity_names(code) == [('contract', 'subcontract')]

# test with a library
code = '''
contract test1 {}
library test2 {}
'''
assert _solidity.solidity_names(code) == [('contract', 'test1'), ('library', 'test2')]


@pytest.mark.skipif(not SOLIDITY_AVAILABLE, reason='solc compiler not available')
def test_library_from_file():
state = tester.state()
Expand Down