-
Notifications
You must be signed in to change notification settings - Fork 45
/
Copy pathindex.ts
149 lines (126 loc) · 4.06 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import fs from 'fs'
import { assert } from 'chai'
import path from 'path'
import * as parser from '../src/index'
import { parseNode, parseStatement } from './utils'
describe('#parse', function () {
it('parses test file correctly', function () {
const testSolPath = path.resolve(__dirname, '..', 'antlr', 'test.sol')
const content = fs.readFileSync(testSolPath)
parser.parse(content.toString())
})
it('throws ParserError on syntax error', function () {
const source = 'contract {'
assert.throws(() => {
parser.parse(source)
}, parser.ParserError)
})
it('supports tolerant mode', function () {
const source = 'contract {'
const root = parser.parse(source, { tolerant: true })
assert.isAbove(root.errors!.length, 0)
})
it('supports loc', function () {
const source = 'contract test { uint a; }'
const root: any = parser.parse(source, { loc: true })
assert.isOk('loc' in root)
})
it('supports range', function () {
const source = 'contract test { uint a; }'
const root = parser.parse(source, { range: true })
assert.isOk('range' in root)
})
it('can build ast with tolerant mode errors', () => {
const cases = [
'contract test { function () { 2 + + 2; } }',
'contract test { modifier { } }',
]
for (const c of cases) {
parser.parse(c, { tolerant: true })
}
})
describe('node meta', function () {
it('adds meta to VariableDeclaration inside StateVariableDeclaration', function () {
const ast = parseNode('uint public a;', { loc: true })
assert.isOk(ast.variables[0].loc)
})
it('adds meta to VariableDeclaration inside VariableDeclarationStatement', function () {
const ast = parseStatement('uint a;', { loc: true })
assert.isOk(ast.variables[0].loc)
})
it('adds meta to VariableDeclaration inside EventDefinition', function () {
const ast = parseNode('event Foo(address bar);', { loc: true })
assert.isOk(ast.parameters[0].loc)
})
})
it('parses empty files', function () {
const ast = parser.parse('')
assert.deepEqual(ast, { type: 'SourceUnit', children: [] })
})
it('parses empty files with loc enabled', function () {
const ast = parser.parse('', { loc: true })
assert.deepEqual(ast, {
type: 'SourceUnit',
children: [],
loc: {
start: {
line: 1,
column: 0,
},
end: {
line: 1,
column: 0,
},
},
})
})
})
describe('#visit', function () {
it('walks visitor through AST', function () {
const source = 'contract test { uint a; }'
const ast = parser.parse(source)
parser.visit(ast, {
ContractDefinition: (node: any) => {
assert.equal(node.type, 'ContractDefinition')
},
'ContractDefinition:exit': (node: any) => {
assert.equal(node.type, 'ContractDefinition')
},
})
})
it('can stop visiting inner nodes by returning false', function () {
const source = 'contract test { uint a; }'
const ast = parser.parse(source)
parser.visit(ast, {
ContractDefinition: () => {
return false
},
'ContractDefinition:exit': () => {
assert.fail('should not reach here')
},
})
})
it("shouldn't print anything if the lexer fails", function () {
const originalConsoleError = console.error
let called = false
console.error = () => (called = true)
parser.parse('"', { tolerant: true })
console.error = originalConsoleError
assert.isFalse(called, 'Should not call console.error on lexer errors')
})
it('should receive an optional parent node', function () {
const source = 'contract test { uint a; }'
const ast = parser.parse(source)
parser.visit(ast, {
StateVariableDeclaration: (node, parent) => {
if (parent === undefined) {
assert.fail('parent node should be defined')
}
if (parent.type !== 'ContractDefinition') {
assert.fail('parent node should be ContractDefinition')
}
assert.equal(parent.name, 'test')
},
})
})
})