Skip to content

Commit

Permalink
add test for reference-to-optional analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent committed Apr 26, 2022
1 parent a393107 commit afc1e51
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 43 deletions.
94 changes: 53 additions & 41 deletions tools/contract-analyzer/analyzers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,51 +24,63 @@ import (
"github.com/onflow/cadence/tools/analysis"
)

var referenceToOptionalElements = []ast.Element{
(*ast.ReferenceExpression)(nil),
}

var referenceToOptionalAnalyzer = &analysis.Analyzer{
Requires: []*analysis.Analyzer{
analysis.InspectorAnalyzer,
},
Run: func(pass *analysis.Pass) interface{} {
inspector := pass.ResultOf[analysis.InspectorAnalyzer].(*ast.Inspector)

location := pass.Program.Location
elaboration := pass.Program.Elaboration
report := pass.Report

inspector.Preorder(
referenceToOptionalElements,
func(element ast.Element) {
referenceExpression, ok := element.(*ast.ReferenceExpression)
if !ok {
return
}

indexExpression, ok := referenceExpression.Expression.(*ast.IndexExpression)
if !ok {
return
}

indexedType := elaboration.IndexExpressionIndexedTypes[indexExpression]
resultType := indexedType.ElementType(false)
_, ok = resultType.(*sema.OptionalType)
if !ok {
return
}

report(
analysis.Diagnostic{
Location: location,
Range: ast.NewRangeFromPositioned(indexExpression),
Message: "reference to optional",
},
)
},
)

return nil
},
}

func init() {
var referenceToOptionalElements = []ast.Element{
(*ast.ReferenceExpression)(nil),
}

registerAnalyzer(
"reference-to-optional",
&analysis.Analyzer{
Requires: []*analysis.Analyzer{
analysis.InspectorAnalyzer,
},
Run: func(pass *analysis.Pass) interface{} {
inspector := pass.ResultOf[analysis.InspectorAnalyzer].(*ast.Inspector)

location := pass.Program.Location
elaboration := pass.Program.Elaboration
report := pass.Report

inspector.Preorder(
referenceToOptionalElements,
func(element ast.Element) {
referenceExpression, ok := element.(*ast.ReferenceExpression)
if !ok {
return
}

indexExpression, ok := referenceExpression.Expression.(*ast.IndexExpression)
if !ok {
return
}

indexedType := elaboration.IndexExpressionIndexedTypes[indexExpression]
resultType := indexedType.ElementType(false)
_, ok = resultType.(*sema.OptionalType)
if !ok {
return
}

report(
analysis.Diagnostic{
Location: location,
Range: ast.NewRangeFromPositioned(indexExpression),
Message: "reference to optional",
},
)
referenceToOptionalAnalyzer,
)
}

},
)

Expand Down
63 changes: 63 additions & 0 deletions tools/contract-analyzer/analyzers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package main

import (
"testing"

"github.com/onflow/cadence/runtime/ast"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/tools/analysis"
"github.com/stretchr/testify/require"
)

func TestReferenceToOptionalAnalyzer(t *testing.T) {

t.Parallel()

const code = `
pub contract Test {
pub fun test() {
let xs: {Int: String} = {0: "zero"}
let ref = &xs[0] as &String
}
}
`

location := common.StringLocation("test")
locationID := location.ID()

config := newAnalysisConfig(
map[common.LocationID]string{
locationID: code,
},
nil,
)

programs, err := analysis.Load(config, location)
require.NoError(t, err)

var diagnostics []analysis.Diagnostic

programs[locationID].Run(
[]*analysis.Analyzer{
referenceToOptionalAnalyzer,
},
func(diagnostic analysis.Diagnostic) {
diagnostics = append(diagnostics, diagnostic)
},
)

require.Equal(
t,
[]analysis.Diagnostic{
{
Range: ast.Range{
StartPos: ast.Position{Offset: 131, Line: 5, Column: 27},
EndPos: ast.Position{Offset: 133, Line: 5, Column: 29},
},
Location: location,
Message: "reference to optional",
},
},
diagnostics,
)
}
10 changes: 8 additions & 2 deletions tools/contract-analyzer/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@ module github.com/onflow/cadence/tools/contract-analyzer

go 1.17

require github.com/onflow/cadence v0.23.4
require (
github.com/onflow/cadence v0.23.4
github.com/stretchr/testify v1.7.1-0.20210824115523-ab6dc3262822
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.4.1-0.20220314011055-12f5cb4b5eb0 // indirect
github.com/fxamacker/circlehash v0.3.0 // indirect
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect
github.com/onflow/atree v0.3.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.1-0.20211004051800-57c86be7915a // indirect
github.com/stretchr/testify v1.7.1-0.20210824115523-ab6dc3262822 // indirect
github.com/x448/float16 v0.8.4 // indirect
github.com/zeebo/blake3 v0.2.2 // indirect
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
golang.org/x/text v0.3.6 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)

replace github.com/onflow/cadence => ../..
3 changes: 3 additions & 0 deletions tools/contract-analyzer/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ github.com/go-test/deep v1.0.5/go.mod h1:QV8Hv/iy04NyLBxAdO9njL0iVPN1S4d/A3NVv1V
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
Expand Down Expand Up @@ -115,6 +117,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
Expand Down

0 comments on commit afc1e51

Please sign in to comment.