• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

unpackdev / solgo / 6570563684

19 Oct 2023 06:07AM UTC coverage: 79.024% (-0.5%) from 79.503%
6570563684

Pull #130

github

0x19
Fixing typename path discovery and bumping go-ethereum
Pull Request #130: AST TypeName uint[] Bugfix

57 of 98 new or added lines in 2 files covered. (58.16%)

76 existing lines in 9 files now uncovered.

15601 of 19742 relevant lines covered (79.02%)

0.87 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

71.83
/ast/function.go
1
package ast
2

3
import (
4
        "encoding/json"
5
        "fmt"
6
        "regexp"
7
        "strings"
8

9
        "github.com/ethereum/go-ethereum/common"
10
        ast_pb "github.com/unpackdev/protos/dist/go/ast"
11
        "github.com/unpackdev/solgo/parser"
12
        "github.com/unpackdev/solgo/utils"
13
)
14

15
// Function represents a Solidity function definition within an abstract syntax tree.
16
type Function struct {
17
        *ASTBuilder // Embedded ASTBuilder for creating the AST.
18

19
        // Core properties of a function node.
20
        Id                    int64                 `json:"id"`
21
        Name                  string                `json:"name"`
22
        NodeType              ast_pb.NodeType       `json:"node_type"`
23
        Kind                  ast_pb.NodeType       `json:"kind"`
24
        Src                   SrcNode               `json:"src"`
25
        NameLocation          SrcNode               `json:"name_location"`
26
        Body                  *BodyNode             `json:"body"`
27
        Implemented           bool                  `json:"implemented"`
28
        Visibility            ast_pb.Visibility     `json:"visibility"`
29
        StateMutability       ast_pb.Mutability     `json:"state_mutability"`
30
        Virtual               bool                  `json:"virtual"`
31
        Modifiers             []*ModifierInvocation `json:"modifiers"`
32
        Overrides             []*OverrideSpecifier  `json:"overrides"`
33
        Parameters            *ParameterList        `json:"parameters"`
34
        ReturnParameters      *ParameterList        `json:"return_parameters"`
35
        SignatureRaw          string                `json:"signature_raw"`
36
        SignatureBytes        []byte                `json:"-"`
37
        Signature             string                `json:"signature"`
38
        Scope                 int64                 `json:"scope"`
39
        ReferencedDeclaration int64                 `json:"referenced_declaration,omitempty"`
40
        TypeDescription       *TypeDescription      `json:"type_description"`
41
}
42

43
// NewFunction creates and initializes a new Function node.
44
func NewFunction(b *ASTBuilder) *Function {
1✔
45
        return &Function{
1✔
46
                ASTBuilder:  b,
1✔
47
                NodeType:    ast_pb.NodeType_FUNCTION_DEFINITION,
1✔
48
                Kind:        ast_pb.NodeType_KIND_FUNCTION,
1✔
49
                Modifiers:   make([]*ModifierInvocation, 0),
1✔
50
                Overrides:   make([]*OverrideSpecifier, 0),
1✔
51
                Implemented: true,
1✔
52
        }
1✔
53
}
1✔
54

55
// SetReferenceDescriptor sets the reference descriptions of the Function node.
56
func (f *Function) SetReferenceDescriptor(refId int64, refDesc *TypeDescription) bool {
1✔
57
        f.ReferencedDeclaration = refId
1✔
58
        f.TypeDescription = refDesc
1✔
59
        return false
1✔
60
}
1✔
61

62
// GetId returns the unique identifier of the Function node.
63
func (f *Function) GetId() int64 {
1✔
64
        return f.Id
1✔
65
}
1✔
66

67
// GetType returns the type of the Function node.
68
func (f *Function) GetType() ast_pb.NodeType {
1✔
69
        return f.NodeType
1✔
70
}
1✔
71

72
// GetSrc returns the source location information of the Function node.
73
func (f *Function) GetSrc() SrcNode {
1✔
74
        return f.Src
1✔
75
}
1✔
76

77
// GetNameLocation returns the source location information of the name of the Function node.
78
func (f *Function) GetNameLocation() SrcNode {
1✔
79
        return f.NameLocation
1✔
80
}
1✔
81

82
// GetParameters returns the list of parameters of the Function node.
83
func (f *Function) GetParameters() *ParameterList {
1✔
84
        return f.Parameters
1✔
85
}
1✔
86

87
// GetReturnParameters returns the list of return parameters of the Function node.
88
func (f *Function) GetReturnParameters() *ParameterList {
1✔
89
        return f.ReturnParameters
1✔
90
}
1✔
91

92
// GetBody returns the body of the Function node.
93
func (f *Function) GetBody() *BodyNode {
1✔
94
        return f.Body
1✔
95
}
1✔
96

97
// GetKind returns the kind of the Function node.
98
func (f *Function) GetKind() ast_pb.NodeType {
1✔
99
        return f.Kind
1✔
100
}
1✔
101

102
// IsImplemented returns true if the Function node is implemented, false otherwise.
103
func (f *Function) IsImplemented() bool {
1✔
104
        return f.Implemented
1✔
105
}
1✔
106

107
// GetModifiers returns the list of modifier invocations applied to the Function node.
108
func (f *Function) GetModifiers() []*ModifierInvocation {
1✔
109
        return f.Modifiers
1✔
110
}
1✔
111

112
// GetOverrides returns the list of override specifiers associated with the Function node.
113
func (f *Function) GetOverrides() []*OverrideSpecifier {
1✔
114
        return f.Overrides
1✔
115
}
1✔
116

117
// GetVisibility returns the visibility of the Function node.
118
func (f *Function) GetVisibility() ast_pb.Visibility {
1✔
119
        return f.Visibility
1✔
120
}
1✔
121

122
// GetStateMutability returns the state mutability of the Function node.
123
func (f *Function) GetStateMutability() ast_pb.Mutability {
1✔
124
        return f.StateMutability
1✔
125
}
1✔
126

127
// IsVirtual returns true if the Function node is declared as virtual, false otherwise.
128
func (f *Function) IsVirtual() bool {
1✔
129
        return f.Virtual
1✔
130
}
1✔
131

132
// GetScope returns the scope of the Function node.
133
func (f *Function) GetScope() int64 {
1✔
134
        return f.Scope
1✔
135
}
1✔
136

137
// GetName returns the name of the Function node.
138
func (f *Function) GetName() string {
1✔
139
        return f.Name
1✔
140
}
1✔
141

142
// GetTypeDescription returns the type description of the Function node.
143
func (f *Function) GetTypeDescription() *TypeDescription {
1✔
144
        return f.TypeDescription
1✔
145
}
1✔
146

147
// ComputeSignature computes the signature of the Function node.
148
func (f *Function) ComputeSignature() {
1✔
149
        params := make([]string, 0)
1✔
150

1✔
151
        if f.GetParameters() != nil {
2✔
152
                for _, param := range f.GetParameters().GetParameters() {
2✔
153
                        params = append(params, param.TypeName.Name)
1✔
154
                }
1✔
155
        }
156
        f.SignatureRaw = strings.Join(
1✔
157
                []string{
1✔
158
                        f.GetName(),
1✔
159
                        "(",
1✔
160
                        strings.Join(params, ", "),
1✔
161
                        ")",
1✔
162
                }, "",
1✔
163
        )
1✔
164
        f.SignatureBytes = utils.Keccak256([]byte(f.SignatureRaw))
1✔
165
        f.Signature = common.Bytes2Hex(f.SignatureBytes[:4])
1✔
166
}
167

168
// GetSignatureRaw returns the raw signature of the Function node.
169
func (f *Function) GetSignatureRaw() string {
1✔
170
        return f.SignatureRaw
1✔
171
}
1✔
172

173
// GetSignatureBytes returns the keccak signature full bytes of the Function node.
174
func (f *Function) GetSignatureBytes() []byte {
1✔
175
        return f.SignatureBytes
1✔
176
}
1✔
177

178
// GetSignature computes the keccak signature of the Function node.
179
func (f *Function) GetSignature() string {
1✔
180
        return f.Signature
1✔
181
}
1✔
182

183
// GetNodes returns a list of child nodes within the Function node.
184
func (f *Function) GetNodes() []Node[NodeType] {
1✔
185
        toReturn := []Node[NodeType]{}
1✔
186
        toReturn = append(toReturn, f.GetBody().GetNodes()...)
1✔
187
        toReturn = append(toReturn, f.GetParameters().GetNodes()...)
1✔
188
        toReturn = append(toReturn, f.GetReturnParameters().GetNodes()...)
1✔
189

1✔
190
        for _, override := range f.GetOverrides() {
2✔
191
                toReturn = append(toReturn, override)
1✔
192
        }
1✔
193

194
        for _, modifier := range f.GetModifiers() {
2✔
195
                toReturn = append(toReturn, modifier)
1✔
196
        }
1✔
197

198
        return toReturn
1✔
199
}
200

201
// GetReferencedDeclaration returns the referenced declaration identifier associated with the Function node.
202
func (f *Function) GetReferencedDeclaration() int64 {
1✔
203
        return f.ReferencedDeclaration
1✔
204
}
1✔
205

206
func (f *Function) UnmarshalJSON(data []byte) error {
1✔
207
        var tempMap map[string]json.RawMessage
1✔
208
        if err := json.Unmarshal(data, &tempMap); err != nil {
1✔
209
                return err
×
210
        }
×
211

212
        if id, ok := tempMap["id"]; ok {
2✔
213
                if err := json.Unmarshal(id, &f.Id); err != nil {
1✔
214
                        return err
×
215
                }
×
216
        }
217

218
        if name, ok := tempMap["name"]; ok {
2✔
219
                if err := json.Unmarshal(name, &f.Name); err != nil {
1✔
220
                        return err
×
221
                }
×
222
        }
223

224
        if nodeType, ok := tempMap["node_type"]; ok {
2✔
225
                if err := json.Unmarshal(nodeType, &f.NodeType); err != nil {
1✔
226
                        return err
×
227
                }
×
228
        }
229

230
        if kind, ok := tempMap["kind"]; ok {
2✔
231
                if err := json.Unmarshal(kind, &f.Kind); err != nil {
1✔
232
                        return err
×
233
                }
×
234
        }
235

236
        if src, ok := tempMap["src"]; ok {
2✔
237
                if err := json.Unmarshal(src, &f.Src); err != nil {
1✔
238
                        return err
×
239
                }
×
240
        }
241

242
        if nameLocation, ok := tempMap["name_location"]; ok {
2✔
243
                if err := json.Unmarshal(nameLocation, &f.NameLocation); err != nil {
1✔
244
                        return err
×
245
                }
×
246
        }
247

248
        if implemented, ok := tempMap["implemented"]; ok {
2✔
249
                if err := json.Unmarshal(implemented, &f.Implemented); err != nil {
1✔
250
                        return err
×
251
                }
×
252
        }
253

254
        if visibility, ok := tempMap["visibility"]; ok {
2✔
255
                if err := json.Unmarshal(visibility, &f.Visibility); err != nil {
1✔
256
                        return err
×
257
                }
×
258
        }
259

260
        if sm, ok := tempMap["state_mutability"]; ok {
2✔
261
                if err := json.Unmarshal(sm, &f.StateMutability); err != nil {
1✔
262
                        return err
×
263
                }
×
264
        }
265

266
        if virtual, ok := tempMap["virtual"]; ok {
2✔
267
                if err := json.Unmarshal(virtual, &f.Virtual); err != nil {
1✔
268
                        return err
×
269
                }
×
270
        }
271

272
        if modifiers, ok := tempMap["modifiers"]; ok {
2✔
273
                if err := json.Unmarshal(modifiers, &f.Modifiers); err != nil {
1✔
274
                        return err
×
275
                }
×
276
        }
277

278
        if overrides, ok := tempMap["overrides"]; ok {
2✔
279
                if err := json.Unmarshal(overrides, &f.Overrides); err != nil {
1✔
280
                        return err
×
281
                }
×
282
        }
283

284
        if params, ok := tempMap["parameters"]; ok {
2✔
285
                if err := json.Unmarshal(params, &f.Parameters); err != nil {
1✔
286
                        return err
×
287
                }
×
288
        }
289

290
        if retParams, ok := tempMap["return_parameters"]; ok {
2✔
291
                if err := json.Unmarshal(retParams, &f.ReturnParameters); err != nil {
1✔
292
                        return err
×
293
                }
×
294
        }
295

296
        if scope, ok := tempMap["scope"]; ok {
2✔
297
                if err := json.Unmarshal(scope, &f.Scope); err != nil {
1✔
298
                        return err
×
299
                }
×
300
        }
301

302
        if refD, ok := tempMap["referenced_declaration"]; ok {
1✔
303
                if err := json.Unmarshal(refD, &f.ReferencedDeclaration); err != nil {
×
304
                        return err
×
305
                }
×
306
        }
307

308
        if td, ok := tempMap["type_description"]; ok {
2✔
309
                if err := json.Unmarshal(td, &f.TypeDescription); err != nil {
1✔
310
                        return err
×
311
                }
×
312
        }
313

314
        if sigRaw, ok := tempMap["signature_raw"]; ok {
2✔
315
                if err := json.Unmarshal(sigRaw, &f.SignatureRaw); err != nil {
1✔
316
                        return err
×
317
                }
×
318
        }
319

320
        if sigBytes, ok := tempMap["signature_bytes"]; ok {
1✔
321
                if err := json.Unmarshal(sigBytes, &f.SignatureBytes); err != nil {
×
322
                        return err
×
323
                }
×
324
        }
325

326
        if sig, ok := tempMap["signature"]; ok {
2✔
327
                if err := json.Unmarshal(sig, &f.Signature); err != nil {
1✔
328
                        return err
×
329
                }
×
330
        }
331

332
        if body, ok := tempMap["body"]; ok {
2✔
333
                if err := json.Unmarshal(body, &f.Body); err != nil {
1✔
334
                        return err
×
335
                }
×
336
        }
337

338
        return nil
1✔
339
}
340

341
// ToProto converts the Function node to its corresponding protobuf representation.
342
func (f *Function) ToProto() NodeType {
1✔
343
        proto := ast_pb.Function{
1✔
344
                Id:                    f.GetId(),
1✔
345
                Name:                  f.GetName(),
1✔
346
                NodeType:              f.GetType(),
1✔
347
                Kind:                  f.GetKind(),
1✔
348
                Src:                   f.GetSrc().ToProto(),
1✔
349
                NameLocation:          f.GetNameLocation().ToProto(),
1✔
350
                ReferencedDeclaration: f.GetReferencedDeclaration(),
1✔
351
                Implemented:           f.IsImplemented(),
1✔
352
                Virtual:               f.IsVirtual(),
1✔
353
                Scope:                 f.GetScope(),
1✔
354
                Visibility:            f.GetVisibility(),
1✔
355
                StateMutability:       f.GetStateMutability(),
1✔
356
                Modifiers:             make([]*ast_pb.ModifierInvocation, 0),
1✔
357
                Overrides:             make([]*ast_pb.OverrideSpecifier, 0),
1✔
358
                Parameters:            f.GetParameters().ToProto(),
1✔
359
                ReturnParameters:      f.GetReturnParameters().ToProto(),
1✔
360
                Body:                  f.GetBody().ToProto().(*ast_pb.Body),
1✔
361
                Signature:             f.GetSignature(),
1✔
362
        }
1✔
363

1✔
364
        if f.GetTypeDescription() != nil {
2✔
365
                proto.TypeDescription = f.GetTypeDescription().ToProto()
1✔
366
        }
1✔
367

368
        for _, modifier := range f.GetModifiers() {
2✔
369
                proto.Modifiers = append(proto.Modifiers, modifier.ToProto().(*ast_pb.ModifierInvocation))
1✔
370
        }
1✔
371

372
        for _, override := range f.GetOverrides() {
2✔
373
                proto.Overrides = append(proto.Overrides, override.ToProto().(*ast_pb.OverrideSpecifier))
1✔
374
        }
1✔
375

376
        return NewTypedStruct(&proto, "Function")
1✔
377
}
378

379
// Parse parses the source code and constructs the Function node.
380
func (f *Function) Parse(
381
        unit *SourceUnit[Node[ast_pb.SourceUnit]],
382
        contractNode Node[NodeType],
383
        bodyCtx parser.IContractBodyElementContext,
384
        ctx *parser.FunctionDefinitionContext,
385
) Node[NodeType] {
1✔
386
        // Initialize basic properties.
1✔
387
        f.Id = f.GetNextID()
1✔
388
        f.Scope = contractNode.GetId()
1✔
389
        if ctx.Identifier() != nil {
2✔
390
                f.Name = ctx.Identifier().GetText()
1✔
391
                f.NameLocation = SrcNode{
1✔
392
                        Line:        int64(ctx.Identifier().GetStart().GetLine()),
1✔
393
                        Column:      int64(ctx.Identifier().GetStart().GetColumn()),
1✔
394
                        Start:       int64(ctx.Identifier().GetStart().GetStart()),
1✔
395
                        End:         int64(ctx.Identifier().GetStop().GetStop()),
1✔
396
                        Length:      int64(ctx.Identifier().GetStop().GetStop() - ctx.Identifier().GetStart().GetStart() + 1),
1✔
397
                        ParentIndex: f.Id,
1✔
398
                }
1✔
399
        }
1✔
400
        f.Implemented = ctx.Block() != nil && !ctx.Block().IsEmpty()
1✔
401
        f.Src = SrcNode{
1✔
402
                Id:          f.GetNextID(),
1✔
403
                Line:        int64(ctx.GetStart().GetLine()),
1✔
404
                Column:      int64(ctx.GetStart().GetColumn()),
1✔
405
                Start:       int64(ctx.GetStart().GetStart()),
1✔
406
                End:         int64(ctx.GetStop().GetStop()),
1✔
407
                Length:      int64(ctx.GetStop().GetStop() - ctx.GetStart().GetStart() + 1),
1✔
408
                ParentIndex: contractNode.GetId(),
1✔
409
        }
1✔
410

1✔
411
        // Set function visibility state.
1✔
412
        f.Visibility = f.getVisibilityFromCtx(ctx)
1✔
413

1✔
414
        // Set function state mutability.
1✔
415
        f.StateMutability = f.getStateMutabilityFromCtx(ctx)
1✔
416

1✔
417
        // Set if function is virtual.
1✔
418
        f.Virtual = f.getVirtualState(ctx)
1✔
419

1✔
420
        // Set function parameters if they exist.
1✔
421
        params := NewParameterList(f.ASTBuilder)
1✔
422
        if len(ctx.AllParameterList()) > 0 {
2✔
423
                params.Parse(unit, f, ctx.AllParameterList()[0])
1✔
424
        } else {
2✔
425
                params.Src = f.Src
1✔
426
                params.Src.ParentIndex = f.Id
1✔
427
        }
1✔
428
        f.Parameters = params
1✔
429

1✔
430
        // Set function modifiers.
1✔
431
        for _, modifierCtx := range ctx.AllModifierInvocation() {
2✔
432
                modifier := NewModifierInvocation(f.ASTBuilder)
1✔
433
                modifier.Parse(unit, contractNode, f, nil, modifierCtx)
1✔
434
                f.Modifiers = append(f.Modifiers, modifier)
1✔
435
        }
1✔
436

437
        // Set function override specifier.
438
        for _, overrideCtx := range ctx.AllOverrideSpecifier() {
2✔
439
                overrideSpecifier := NewOverrideSpecifier(f.ASTBuilder)
1✔
440
                overrideSpecifier.Parse(unit, f, overrideCtx)
1✔
441
                f.Overrides = append(f.Overrides, overrideSpecifier)
1✔
442
        }
1✔
443

444
        // Set function return parameters if they exist.
445
        // @TODO: Consider traversing through body to discover name of the return parameters even
446
        // if they are not defined in (name uint) format.
447
        returnParams := NewParameterList(f.ASTBuilder)
1✔
448
        if ctx.GetReturnParameters() != nil {
2✔
449
                returnParams.Parse(unit, f, ctx.GetReturnParameters())
1✔
450
        } else {
2✔
451
                returnParams.Src = f.Src
1✔
452
                returnParams.Src.ParentIndex = f.Id
1✔
453
        }
1✔
454
        f.ReturnParameters = returnParams
1✔
455

1✔
456
        if ctx.Block() != nil && !ctx.Block().IsEmpty() {
2✔
457
                bodyNode := NewBodyNode(f.ASTBuilder, false)
1✔
458
                bodyNode.ParseBlock(unit, contractNode, f, ctx.Block())
1✔
459
                f.Body = bodyNode
1✔
460

1✔
461
                // In case at any point we discover that the function is not implemented, we set the
1✔
462
                // implemented flag to false.
1✔
463
                if !bodyNode.Implemented {
1✔
464
                        f.Implemented = false
×
465
                }
×
466

467
                if ctx.Block().AllUncheckedBlock() != nil {
2✔
468
                        for _, uncheckedCtx := range ctx.Block().AllUncheckedBlock() {
2✔
469
                                bodyNode := NewBodyNode(f.ASTBuilder, false)
1✔
470
                                bodyNode.ParseUncheckedBlock(unit, contractNode, f, uncheckedCtx)
1✔
471
                                f.Body.Statements = append(f.Body.Statements, bodyNode)
1✔
472

1✔
473
                                // In case at any point we discover that the function is not implemented, we set the
1✔
474
                                // implemented flag to false.
1✔
475
                                if !bodyNode.Implemented {
2✔
476
                                        f.Implemented = false
1✔
477
                                }
1✔
478
                        }
479
                }
480
        } else {
1✔
481
                bodyNode := NewBodyNode(f.ASTBuilder, false)
1✔
482
                bodyNode.Src = f.Src
1✔
483
                bodyNode.Src.ParentIndex = f.Id
1✔
484
                f.Body = bodyNode
1✔
485
        }
1✔
486

487
        f.TypeDescription = f.buildTypeDescription()
1✔
488

1✔
489
        f.ComputeSignature()
1✔
490

1✔
491
        f.currentFunctions = append(f.currentFunctions, f)
1✔
492

1✔
493
        return f
1✔
494
}
495

496
// ParseTypeName parses the source code and constructs the Function node for TypeName.
497
func (f *Function) ParseTypeName(
498
        unit *SourceUnit[Node[ast_pb.SourceUnit]],
499
        parentNodeId int64,
500
        ctx *parser.FunctionTypeNameContext,
501
) Node[NodeType] {
×
502
        // Initialize basic properties.
×
503
        f.Id = f.GetNextID()
×
504
        f.Scope = unit.GetId()
×
505
        f.Src = SrcNode{
×
506
                Id:          f.GetNextID(),
×
507
                Line:        int64(ctx.GetStart().GetLine()),
×
508
                Column:      int64(ctx.GetStart().GetColumn()),
×
509
                Start:       int64(ctx.GetStart().GetStart()),
×
510
                End:         int64(ctx.GetStop().GetStop()),
×
511
                Length:      int64(ctx.GetStop().GetStop() - ctx.GetStart().GetStart() + 1),
×
512
                ParentIndex: parentNodeId,
×
513
        }
×
514

×
515
        // Set function visibility state.
×
516
        f.Visibility = f.getVisibilityFromTypeNameCtx(ctx)
×
517

×
518
        // Set function state mutability.
×
519
        f.StateMutability = f.getStateMutabilityFromTypeNameCtx(ctx)
×
520

×
521
        // Set function parameters if they exist.
×
522
        params := NewParameterList(f.ASTBuilder)
×
523
        if len(ctx.AllParameterList()) > 0 {
×
524
                params.Parse(unit, f, ctx.AllParameterList()[0])
×
525
        } else {
×
526
                params.Src = f.Src
×
527
                params.Src.ParentIndex = f.Id
×
528
        }
×
529
        f.Parameters = params
×
530

×
531
        // Set function return parameters if they exist.
×
532
        // @TODO: Consider traversing through body to discover name of the return parameters even
×
533
        // if they are not defined in (name uint) format.
×
534
        returnParams := NewParameterList(f.ASTBuilder)
×
535
        if ctx.GetReturnParameters() != nil {
×
536
                returnParams.Parse(unit, f, ctx.GetReturnParameters())
×
537
        } else {
×
538
                returnParams.Src = f.Src
×
539
                returnParams.Src.ParentIndex = f.Id
×
540
        }
×
541
        f.ReturnParameters = returnParams
×
542

×
543
        bodyNode := NewBodyNode(f.ASTBuilder, false)
×
544
        bodyNode.Src = f.Src
×
545
        bodyNode.Src.ParentIndex = f.Id
×
546
        f.Body = bodyNode
×
547

×
548
        f.TypeDescription = f.buildTypeDescription()
×
549

×
550
        f.ComputeSignature()
×
551

×
552
        f.currentFunctions = append(f.currentFunctions, f)
×
553

×
554
        return f
×
555
}
556

557
// buildTypeDescription constructs the type description of the Function node.
558
func (f *Function) buildTypeDescription() *TypeDescription {
1✔
559
        typeString := "function("
1✔
560
        typeIdentifier := "t_function_"
1✔
561
        typeStrings := make([]string, 0)
1✔
562
        typeIdentifiers := make([]string, 0)
1✔
563

1✔
564
        for _, paramType := range f.GetParameters().GetParameterTypes() {
2✔
565
                if paramType == nil {
1✔
UNCOV
566
                        typeStrings = append(typeStrings, fmt.Sprintf("unknown_%d", f.GetId()))
×
UNCOV
567
                        typeIdentifiers = append(typeIdentifiers, fmt.Sprintf("$_t_unknown_%d", f.GetId()))
×
UNCOV
568
                        continue
×
569
                }
570

571
                typeStrings = append(typeStrings, paramType.TypeString)
1✔
572
                typeIdentifiers = append(typeIdentifiers, "$_"+paramType.TypeIdentifier)
1✔
573
        }
574
        typeString += strings.Join(typeStrings, ",") + ")"
1✔
575
        typeIdentifier += strings.Join(typeIdentifiers, "$")
1✔
576

1✔
577
        if !strings.HasSuffix(typeIdentifier, "$") {
2✔
578
                typeIdentifier += "$"
1✔
579
        }
1✔
580

581
        re := regexp.MustCompile(`\${2,}`)
1✔
582
        typeIdentifier = re.ReplaceAllString(typeIdentifier, "$")
1✔
583

1✔
584
        return &TypeDescription{
1✔
585
                TypeString:     typeString,
1✔
586
                TypeIdentifier: typeIdentifier,
1✔
587
        }
1✔
588
}
589

590
// getVisibilityFromCtx extracts the visibility of the Function node from the parser context.
591
func (f *Function) getVisibilityFromCtx(ctx *parser.FunctionDefinitionContext) ast_pb.Visibility {
1✔
592
        visibilityMap := map[string]ast_pb.Visibility{
1✔
593
                "public":   ast_pb.Visibility_PUBLIC,
1✔
594
                "private":  ast_pb.Visibility_PRIVATE,
1✔
595
                "internal": ast_pb.Visibility_INTERNAL,
1✔
596
                "external": ast_pb.Visibility_EXTERNAL,
1✔
597
        }
1✔
598

1✔
599
        for _, visibility := range ctx.AllVisibility() {
2✔
600
                if v, ok := visibilityMap[visibility.GetText()]; ok {
2✔
601
                        return v
1✔
602
                }
1✔
603
        }
604

605
        return ast_pb.Visibility_INTERNAL
×
606
}
607

608
// getVisibilityFromTypeNameCtx extracts the visibility of the Function node from the parser context.
609
func (f *Function) getVisibilityFromTypeNameCtx(ctx *parser.FunctionTypeNameContext) ast_pb.Visibility {
×
610
        visibilityMap := map[string]ast_pb.Visibility{
×
611
                "public":   ast_pb.Visibility_PUBLIC,
×
612
                "private":  ast_pb.Visibility_PRIVATE,
×
613
                "internal": ast_pb.Visibility_INTERNAL,
×
614
                "external": ast_pb.Visibility_EXTERNAL,
×
615
        }
×
616

×
617
        for _, visibility := range ctx.AllVisibility() {
×
618
                if v, ok := visibilityMap[visibility.GetText()]; ok {
×
619
                        return v
×
620
                }
×
621
        }
622

623
        return ast_pb.Visibility_INTERNAL
×
624
}
625

626
// getStateMutabilityFromCtx extracts the state mutability of the Function node from the parser context.
627
func (f *Function) getStateMutabilityFromCtx(ctx *parser.FunctionDefinitionContext) ast_pb.Mutability {
1✔
628
        mutabilityMap := map[string]ast_pb.Mutability{
1✔
629
                "payable": ast_pb.Mutability_PAYABLE,
1✔
630
                "pure":    ast_pb.Mutability_PURE,
1✔
631
                "view":    ast_pb.Mutability_VIEW,
1✔
632
        }
1✔
633

1✔
634
        for _, stateMutability := range ctx.AllStateMutability() {
2✔
635
                if m, ok := mutabilityMap[stateMutability.GetText()]; ok {
2✔
636
                        return m
1✔
637
                }
1✔
638
        }
639

640
        return ast_pb.Mutability_NONPAYABLE
1✔
641
}
642

643
// getStateMutabilityFromTypeNameCtx extracts the state mutability of the Function node from the parser context.
644
func (f *Function) getStateMutabilityFromTypeNameCtx(ctx *parser.FunctionTypeNameContext) ast_pb.Mutability {
×
645
        mutabilityMap := map[string]ast_pb.Mutability{
×
646
                "payable": ast_pb.Mutability_PAYABLE,
×
647
                "pure":    ast_pb.Mutability_PURE,
×
648
                "view":    ast_pb.Mutability_VIEW,
×
649
        }
×
650

×
651
        for _, stateMutability := range ctx.AllStateMutability() {
×
652
                if m, ok := mutabilityMap[stateMutability.GetText()]; ok {
×
653
                        return m
×
654
                }
×
655
        }
656

657
        return ast_pb.Mutability_NONPAYABLE
×
658
}
659

660
// getVirtualState determines if the Function node is declared as virtual from the parser context.
661
func (f *Function) getVirtualState(ctx *parser.FunctionDefinitionContext) bool {
1✔
662
        for _, virtual := range ctx.AllVirtual() {
2✔
663
                if virtual.GetText() == "virtual" {
2✔
664
                        return true
1✔
665
                }
1✔
666
        }
667

668
        return false
1✔
669
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc