Documentation
¶
Index ¶
- Constants
- Variables
- func ReplacementHint(expr ast.Expression, location common.Location, r ast.Range) *analysis.Diagnostic
- type CheckCastVisitor
- func (d *CheckCastVisitor) IsRedundantCast(expr ast.Expression, exprInferredType, targetType sema.Type) bool
- func (d *CheckCastVisitor) VisitArrayExpression(expr *ast.ArrayExpression) bool
- func (d *CheckCastVisitor) VisitBinaryExpression(_ *ast.BinaryExpression) bool
- func (d *CheckCastVisitor) VisitBoolExpression(_ *ast.BoolExpression) bool
- func (d *CheckCastVisitor) VisitCastingExpression(_ *ast.CastingExpression) bool
- func (d *CheckCastVisitor) VisitConditionalExpression(conditionalExpr *ast.ConditionalExpression) bool
- func (d *CheckCastVisitor) VisitCreateExpression(_ *ast.CreateExpression) bool
- func (d *CheckCastVisitor) VisitDestroyExpression(_ *ast.DestroyExpression) bool
- func (d *CheckCastVisitor) VisitDictionaryExpression(expr *ast.DictionaryExpression) bool
- func (d *CheckCastVisitor) VisitFixedPointExpression(expr *ast.FixedPointExpression) bool
- func (d *CheckCastVisitor) VisitForceExpression(_ *ast.ForceExpression) bool
- func (d *CheckCastVisitor) VisitFunctionExpression(_ *ast.FunctionExpression) bool
- func (d *CheckCastVisitor) VisitIdentifierExpression(_ *ast.IdentifierExpression) bool
- func (d *CheckCastVisitor) VisitIndexExpression(_ *ast.IndexExpression) bool
- func (d *CheckCastVisitor) VisitIntegerExpression(_ *ast.IntegerExpression) bool
- func (d *CheckCastVisitor) VisitInvocationExpression(_ *ast.InvocationExpression) bool
- func (d *CheckCastVisitor) VisitMemberExpression(_ *ast.MemberExpression) bool
- func (d *CheckCastVisitor) VisitNilExpression(_ *ast.NilExpression) bool
- func (d *CheckCastVisitor) VisitPathExpression(_ *ast.PathExpression) bool
- func (d *CheckCastVisitor) VisitReferenceExpression(_ *ast.ReferenceExpression) bool
- func (d *CheckCastVisitor) VisitStringExpression(_ *ast.StringExpression) bool
- func (d *CheckCastVisitor) VisitUnaryExpression(_ *ast.UnaryExpression) bool
- func (d *CheckCastVisitor) VisitVoidExpression(_ *ast.VoidExpression) bool
- type Config
- type Linter
- func (l *Linter) AnalyzeAccount(address string, networkName string)
- func (l *Linter) AnalyzeCSV(path string)
- func (l *Linter) AnalyzeDirectory(directory string)
- func (l *Linter) AnalyzeTransaction(transactionID flow.Identifier, networkName string)
- func (l *Linter) PrettyPrintError(err error, location common.Location)
Constants ¶
View Source
const ( ReplacementCategory string = "replacement-hint" RemovalCategory string = "removal-hint" UpdateCategory string = "update recommended" UnnecessaryCastCategory string = "unnecessary-cast-hint" )
View Source
const LoadMode = analysis.NeedTypes | analysis.NeedExtendedElaboration
Variables ¶
View Source
var Analyzers = map[string]*analysis.Analyzer{}
View Source
var DeprecatedKeyFunctionsAnalyzer = (func() *analysis.Analyzer { elementFilter := []ast.Element{ (*ast.InvocationExpression)(nil), } return &analysis.Analyzer{ Description: "Detects usages of the deprecated key management API. It will be removed in a future release.", 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( elementFilter, func(element ast.Element) { invocationExpression, ok := element.(*ast.InvocationExpression) if !ok { return } memberExpression, ok := invocationExpression.InvokedExpression.(*ast.MemberExpression) if !ok { return } memberInfo := elaboration.MemberExpressionMemberInfos[memberExpression] member := memberInfo.Member if member == nil { return } if member.ContainerType != sema.AuthAccountType { return } var replacement string functionName := member.Identifier.Identifier switch functionName { case sema.AuthAccountAddPublicKeyField: replacement = "keys.add" case sema.AuthAccountRemovePublicKeyField: replacement = "keys.revoke" default: return } report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, memberExpression.Identifier), Category: UpdateCategory, Message: fmt.Sprintf( "deprecated function '%s' will get removed", functionName, ), SecondaryMessage: fmt.Sprintf( "replace with '%s'", replacement, ), }, ) }, ) return nil }, } })()
View Source
var NumberFunctionArgumentAnalyzer = (func() *analysis.Analyzer { elementFilter := []ast.Element{ (*ast.IntegerExpression)(nil), (*ast.FixedPointExpression)(nil), } return &analysis.Analyzer{ Description: "Detects redundant uses of number conversion functions.", 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( elementFilter, func(element ast.Element) { var diagnostic *analysis.Diagnostic switch expr := element.(type) { case *ast.IntegerExpression: argumentData, ok := elaboration.NumberConversionArgumentTypes[expr] if !ok { return } diagnostic = suggestIntegerLiteralConversionReplacement(expr, location, argumentData.Type, argumentData.Range) case *ast.FixedPointExpression: argumentData, ok := elaboration.NumberConversionArgumentTypes[expr] if !ok { return } diagnostic = suggestFixedPointLiteralConversionReplacement(expr, location, argumentData.Type, argumentData.Range) default: return } if diagnostic != nil { report(*diagnostic) } }, ) return nil }, } })()
View Source
var RedundantCastAnalyzer = (func() *analysis.Analyzer { elementFilter := []ast.Element{ (*ast.CastingExpression)(nil), } return &analysis.Analyzer{ Description: "Detects unnecessary cast expressions", 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( elementFilter, func(element ast.Element) { castingExpression, ok := element.(*ast.CastingExpression) if !ok { return } redundantType, ok := elaboration.StaticCastTypes[castingExpression] if ok && isRedundantCast(castingExpression.Expression, redundantType.ExprActualType, redundantType.TargetType, redundantType.ExpectedType, ) { report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, castingExpression.TypeAnnotation), Category: UnnecessaryCastCategory, Message: fmt.Sprintf("cast to `%s` is redundant", redundantType.TargetType), }, ) return } alwaysSucceedingTypes, ok := elaboration.RuntimeCastTypes[castingExpression] if ok && sema.IsSubType(alwaysSucceedingTypes.Left, alwaysSucceedingTypes.Right) { switch castingExpression.Operation { case ast.OperationFailableCast: report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, castingExpression), Category: UnnecessaryCastCategory, Message: fmt.Sprintf("failable cast ('%s') from `%s` to `%s` always succeeds", ast.OperationFailableCast.Symbol(), alwaysSucceedingTypes.Left, alwaysSucceedingTypes.Right), }, ) case ast.OperationForceCast: report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, castingExpression), Category: UnnecessaryCastCategory, Message: fmt.Sprintf("force cast ('%s') from `%s` to `%s` always succeeds", ast.OperationForceCast.Symbol(), alwaysSucceedingTypes.Left, alwaysSucceedingTypes.Right), }, ) default: panic(errors.NewUnreachableError()) } } }, ) return nil }, } })()
View Source
var ReferenceOperatorAnalyzer = (func() *analysis.Analyzer { elementFilter := []ast.Element{ (*ast.ReferenceExpression)(nil), } invalidOperatorRegexp := regexp.MustCompile(`.*\bas[?!].*`) return &analysis.Analyzer{ Description: "Detects invalid operators in reference expressions. These will get rejected in a future release.", Requires: []*analysis.Analyzer{ analysis.InspectorAnalyzer, }, Run: func(pass *analysis.Pass) interface{} { inspector := pass.ResultOf[analysis.InspectorAnalyzer].(*ast.Inspector) location := pass.Program.Location code := pass.Program.Code report := pass.Report inspector.Preorder( elementFilter, func(element ast.Element) { referenceExpression, ok := element.(*ast.ReferenceExpression) if !ok { return } startOffset := referenceExpression.Expression.EndPosition(nil).Offset + 1 endOffset := referenceExpression.Type.StartPosition().Offset - 1 if !invalidOperatorRegexp.Match(code[startOffset:endOffset]) { return } report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, element), Category: UpdateCategory, Message: "incorrect reference operator used", SecondaryMessage: fmt.Sprintf( "use the '%s' operator", ast.OperationCast.Symbol(), ), }, ) }, ) return nil }, } })()
View Source
var UnnecessaryForceAnalyzer = (func() *analysis.Analyzer { elementFilter := []ast.Element{ (*ast.ForceExpression)(nil), } return &analysis.Analyzer{ Description: "Detects unnecessary uses of the force operator", 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( elementFilter, func(element ast.Element) { forceExpression, ok := element.(*ast.ForceExpression) if !ok { return } valueType := elaboration.ForceExpressionTypes[forceExpression] if valueType == nil { return } _, ok = valueType.(*sema.OptionalType) if !ok { report( analysis.Diagnostic{ Location: location, Range: ast.NewRangeFromPositioned(nil, element), Category: RemovalCategory, Message: "unnecessary force operator", }, ) } }, ) return nil }, } })()
Functions ¶
func ReplacementHint ¶
func ReplacementHint( expr ast.Expression, location common.Location, r ast.Range, ) *analysis.Diagnostic
Types ¶
type CheckCastVisitor ¶
type CheckCastVisitor struct {
// contains filtered or unexported fields
}
func (*CheckCastVisitor) IsRedundantCast ¶
func (d *CheckCastVisitor) IsRedundantCast(expr ast.Expression, exprInferredType, targetType sema.Type) bool
func (*CheckCastVisitor) VisitArrayExpression ¶
func (d *CheckCastVisitor) VisitArrayExpression(expr *ast.ArrayExpression) bool
func (*CheckCastVisitor) VisitBinaryExpression ¶
func (d *CheckCastVisitor) VisitBinaryExpression(_ *ast.BinaryExpression) bool
func (*CheckCastVisitor) VisitBoolExpression ¶
func (d *CheckCastVisitor) VisitBoolExpression(_ *ast.BoolExpression) bool
func (*CheckCastVisitor) VisitCastingExpression ¶
func (d *CheckCastVisitor) VisitCastingExpression(_ *ast.CastingExpression) bool
func (*CheckCastVisitor) VisitConditionalExpression ¶
func (d *CheckCastVisitor) VisitConditionalExpression(conditionalExpr *ast.ConditionalExpression) bool
func (*CheckCastVisitor) VisitCreateExpression ¶
func (d *CheckCastVisitor) VisitCreateExpression(_ *ast.CreateExpression) bool
func (*CheckCastVisitor) VisitDestroyExpression ¶
func (d *CheckCastVisitor) VisitDestroyExpression(_ *ast.DestroyExpression) bool
func (*CheckCastVisitor) VisitDictionaryExpression ¶
func (d *CheckCastVisitor) VisitDictionaryExpression(expr *ast.DictionaryExpression) bool
func (*CheckCastVisitor) VisitFixedPointExpression ¶
func (d *CheckCastVisitor) VisitFixedPointExpression(expr *ast.FixedPointExpression) bool
func (*CheckCastVisitor) VisitForceExpression ¶
func (d *CheckCastVisitor) VisitForceExpression(_ *ast.ForceExpression) bool
func (*CheckCastVisitor) VisitFunctionExpression ¶
func (d *CheckCastVisitor) VisitFunctionExpression(_ *ast.FunctionExpression) bool
func (*CheckCastVisitor) VisitIdentifierExpression ¶
func (d *CheckCastVisitor) VisitIdentifierExpression(_ *ast.IdentifierExpression) bool
func (*CheckCastVisitor) VisitIndexExpression ¶
func (d *CheckCastVisitor) VisitIndexExpression(_ *ast.IndexExpression) bool
func (*CheckCastVisitor) VisitIntegerExpression ¶
func (d *CheckCastVisitor) VisitIntegerExpression(_ *ast.IntegerExpression) bool
func (*CheckCastVisitor) VisitInvocationExpression ¶
func (d *CheckCastVisitor) VisitInvocationExpression(_ *ast.InvocationExpression) bool
func (*CheckCastVisitor) VisitMemberExpression ¶
func (d *CheckCastVisitor) VisitMemberExpression(_ *ast.MemberExpression) bool
func (*CheckCastVisitor) VisitNilExpression ¶
func (d *CheckCastVisitor) VisitNilExpression(_ *ast.NilExpression) bool
func (*CheckCastVisitor) VisitPathExpression ¶
func (d *CheckCastVisitor) VisitPathExpression(_ *ast.PathExpression) bool
func (*CheckCastVisitor) VisitReferenceExpression ¶
func (d *CheckCastVisitor) VisitReferenceExpression(_ *ast.ReferenceExpression) bool
func (*CheckCastVisitor) VisitStringExpression ¶
func (d *CheckCastVisitor) VisitStringExpression(_ *ast.StringExpression) bool
func (*CheckCastVisitor) VisitUnaryExpression ¶
func (d *CheckCastVisitor) VisitUnaryExpression(_ *ast.UnaryExpression) bool
func (*CheckCastVisitor) VisitVoidExpression ¶
func (d *CheckCastVisitor) VisitVoidExpression(_ *ast.VoidExpression) bool
type Linter ¶
type Linter struct { Config Config Codes map[common.Location][]byte // contains filtered or unexported fields }
func (*Linter) AnalyzeAccount ¶
func (*Linter) AnalyzeCSV ¶
func (*Linter) AnalyzeDirectory ¶
func (*Linter) AnalyzeTransaction ¶
Source Files
¶
Click to show internal directories.
Click to hide internal directories.