From ad9dbaf95f02c18e2ecfa17d05cb16abee89bc2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 27 Feb 2023 16:00:48 -0800 Subject: [PATCH 1/4] add type assertions for error types with SecondaryError function --- runtime/interpreter/errors.go | 1 + runtime/parser/errors.go | 1 + runtime/sema/errors.go | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/runtime/interpreter/errors.go b/runtime/interpreter/errors.go index afef67c22e..085b2c779b 100644 --- a/runtime/interpreter/errors.go +++ b/runtime/interpreter/errors.go @@ -246,6 +246,7 @@ type DereferenceError struct { } var _ errors.UserError = DereferenceError{} +var _ errors.SecondaryError = DereferenceError{} func (DereferenceError) IsUserError() {} diff --git a/runtime/parser/errors.go b/runtime/parser/errors.go index ec5e2ec26b..e870aacbd4 100644 --- a/runtime/parser/errors.go +++ b/runtime/parser/errors.go @@ -133,6 +133,7 @@ type InvalidIntegerLiteralError struct { var _ ParseError = &InvalidIntegerLiteralError{} var _ errors.UserError = &InvalidIntegerLiteralError{} +var _ errors.SecondaryError = &InvalidIntegerLiteralError{} func (*InvalidIntegerLiteralError) isParseError() {} diff --git a/runtime/sema/errors.go b/runtime/sema/errors.go index dfccfb0e23..74e917d86f 100644 --- a/runtime/sema/errors.go +++ b/runtime/sema/errors.go @@ -247,6 +247,7 @@ type AssignmentToConstantError struct { var _ SemanticError = &AssignmentToConstantError{} var _ errors.UserError = &AssignmentToConstantError{} +var _ errors.SecondaryError = &AssignmentToConstantError{} func (*AssignmentToConstantError) isSemanticError() {} @@ -536,8 +537,8 @@ type InvalidBinaryOperandError struct { } var _ SemanticError = &InvalidBinaryOperandError{} -var _ errors.SecondaryError = &InvalidBinaryOperandError{} var _ errors.UserError = &InvalidBinaryOperandError{} +var _ errors.SecondaryError = &InvalidBinaryOperandError{} func (*InvalidBinaryOperandError) isSemanticError() {} @@ -616,8 +617,9 @@ type ControlStatementError struct { ast.Range } -var _ errors.UserError = &ControlStatementError{} var _ SemanticError = &ControlStatementError{} +var _ errors.UserError = &ControlStatementError{} +var _ errors.SecondaryError = &ControlStatementError{} func (*ControlStatementError) isSemanticError() {} @@ -1050,6 +1052,7 @@ type FieldTypeNotStorableError struct { var _ SemanticError = &FieldTypeNotStorableError{} var _ errors.UserError = &FieldTypeNotStorableError{} +var _ errors.SecondaryError = &FieldTypeNotStorableError{} func (*FieldTypeNotStorableError) isSemanticError() {} @@ -1182,6 +1185,7 @@ type InvalidEnumRawTypeError struct { var _ SemanticError = &InvalidEnumRawTypeError{} var _ errors.UserError = &InvalidEnumRawTypeError{} +var _ errors.SecondaryError = &InvalidEnumRawTypeError{} func (*InvalidEnumRawTypeError) isSemanticError() {} @@ -1267,6 +1271,7 @@ type ConformanceError struct { var _ SemanticError = &ConformanceError{} var _ errors.UserError = &ConformanceError{} +var _ errors.SecondaryError = &ConformanceError{} func (*ConformanceError) isSemanticError() {} @@ -2323,6 +2328,7 @@ type InvalidResourceAssignmentError struct { var _ SemanticError = &InvalidResourceAssignmentError{} var _ errors.UserError = &InvalidResourceAssignmentError{} +var _ errors.SecondaryError = &InvalidResourceAssignmentError{} func (*InvalidResourceAssignmentError) isSemanticError() {} @@ -2481,6 +2487,7 @@ type UnreachableStatementError struct { var _ SemanticError = &UnreachableStatementError{} var _ errors.UserError = &UnreachableStatementError{} +var _ errors.SecondaryError = &UnreachableStatementError{} func (*UnreachableStatementError) isSemanticError() {} @@ -3487,6 +3494,7 @@ type InvalidPathIdentifierError struct { var _ SemanticError = &InvalidPathDomainError{} var _ errors.UserError = &InvalidPathDomainError{} +var _ errors.SecondaryError = &InvalidPathDomainError{} func (*InvalidPathDomainError) isSemanticError() {} @@ -3649,6 +3657,7 @@ type TypeParameterTypeMismatchError struct { var _ SemanticError = &TypeParameterTypeMismatchError{} var _ errors.UserError = &TypeParameterTypeMismatchError{} +var _ errors.SecondaryError = &TypeParameterTypeMismatchError{} func (*TypeParameterTypeMismatchError) isSemanticError() {} @@ -3832,6 +3841,7 @@ type ExternalMutationError struct { var _ SemanticError = &ExternalMutationError{} var _ errors.UserError = &ExternalMutationError{} +var _ errors.SecondaryError = &ExternalMutationError{} func (*ExternalMutationError) isSemanticError() {} From 781ac8e60480a18c55f0f4d0561e707c8fd1c72d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 27 Feb 2023 16:01:52 -0800 Subject: [PATCH 2/4] optimize not-declared member error's find closest member function avoid allocation of new slice of member names for iteration --- runtime/sema/errors.go | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/runtime/sema/errors.go b/runtime/sema/errors.go index 74e917d86f..983df1f6a9 100644 --- a/runtime/sema/errors.go +++ b/runtime/sema/errors.go @@ -24,7 +24,6 @@ import ( "strings" "github.com/texttheater/golang-levenshtein/levenshtein" - "golang.org/x/exp/maps" "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" @@ -945,13 +944,20 @@ func (e *NotDeclaredMemberError) findClosestMember() (closestMember string) { return } + nameRunes := []rune(e.Name) + closestDistance := len(e.Name) - for _, member := range maps.Keys(e.Type.GetMembers()) { - distance := levenshtein.DistanceForStrings([]rune(e.Name), []rune(member), levenshtein.DefaultOptions) - // don't update the closest member if the distance is greater than one already found, or if the edits - // required would involve a complete replacement of the member's text - if distance < closestDistance && distance < len(member) { - closestMember = member + for memberName := range e.Type.GetMembers() { + distance := levenshtein.DistanceForStrings( + nameRunes, + []rune(memberName), + levenshtein.DefaultOptions, + ) + + // Don't update the closest member if the distance is greater than one already found, + // or if the edits required would involve a complete replacement of the member's text + if distance < closestDistance && distance < len(memberName) { + closestMember = memberName closestDistance = distance } } From dc587a55c6e241ae8b1201c72f92f5b4c6799d4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 28 Feb 2023 12:11:32 -0800 Subject: [PATCH 3/4] go mod tidy --- go.mod | 1 - go.sum | 2 -- 2 files changed, 3 deletions(-) diff --git a/go.mod b/go.mod index 1f8b1555f9..3e4ad65a30 100644 --- a/go.mod +++ b/go.mod @@ -45,7 +45,6 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/zeebo/blake3 v0.2.3 // indirect - golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 golang.org/x/lint v0.0.0-20200302205851-738671d3881b // indirect golang.org/x/sys v0.1.0 // indirect golang.org/x/term v0.1.0 // indirect diff --git a/go.sum b/go.sum index afa16862eb..c9dc178401 100644 --- a/go.sum +++ b/go.sum @@ -94,8 +94,6 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= -golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9 h1:yZNXmy+j/JpX19vZkVktWqAo7Gny4PBWYYK3zskGpx4= -golang.org/x/exp v0.0.0-20221126150942-6ab00d035af9/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= From b5f57e9f408ae81095837d25d9fd15ead56c9696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Tue, 28 Feb 2023 12:56:40 -0800 Subject: [PATCH 4/4] sort member names --- runtime/sema/errors.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/runtime/sema/errors.go b/runtime/sema/errors.go index 983df1f6a9..0f839199fb 100644 --- a/runtime/sema/errors.go +++ b/runtime/sema/errors.go @@ -21,6 +21,7 @@ package sema import ( "fmt" "math/big" + "sort" "strings" "github.com/texttheater/golang-levenshtein/levenshtein" @@ -947,7 +948,14 @@ func (e *NotDeclaredMemberError) findClosestMember() (closestMember string) { nameRunes := []rune(e.Name) closestDistance := len(e.Name) - for memberName := range e.Type.GetMembers() { + + var sortedMemberNames []string + for memberName := range e.Type.GetMembers() { //nolint:maprange + sortedMemberNames = append(sortedMemberNames, memberName) + } + sort.Strings(sortedMemberNames) + + for _, memberName := range sortedMemberNames { distance := levenshtein.DistanceForStrings( nameRunes, []rune(memberName),