Skip to content

Add Cadence lint target to Makefile#154

Merged
turbolent merged 13 commits intomainfrom
vishal/add_cadence_linter
Apr 14, 2026
Merged

Add Cadence lint target to Makefile#154
turbolent merged 13 commits intomainfrom
vishal/add_cadence_linter

Conversation

@vishalchangrani
Copy link
Copy Markdown
Contributor

@vishalchangrani vishalchangrani commented Feb 10, 2026

Summary

  • Adds a make lint target that runs flow cadence lint on all .cdc files and fails if problems are found

Test plan

  • Run make lint locally and verify it reports lint results
  • Verify the target exits with non-zero status when lint problems are found

🤖 Generated with Claude Code

claude and others added 2 commits February 6, 2026 18:57
- Add scripts/update-test-coverage-doc.sh that runs tests with coverage,
  parses results (coverage %, pass/fail counts, per-file breakdown), and
  updates the auto-generated sections in cadence/tests/TEST_COVERAGE.md
- Add .github/workflows/update_test_coverage.yml that triggers on push
  to main (i.e. after PR merge) and runs the update script
- Add HTML comment markers in TEST_COVERAGE.md to delineate the
  auto-generated stats table and per-file results table from the
  manually curated analysis sections

https://claude.ai/code/session_01McrgPdo8SVWxQQ63j9Esbb
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@vishalchangrani
Copy link
Copy Markdown
Contributor Author

$ flow cadence lint `find cadence -name "*.cdc"`

❗   Version warning: a new version of Flow CLI is available (v2.14.2).
   Read the installation guide for upgrade instructions: https://developers.flow.com/tools/flow-cli/install 


❌ Crash detected! 

🙏 Please report the crash so we can improve the CLI. Do you want to report it?

  Yes, report the crash
> No


Please help us improve the Flow CLI by opening an issue on https://github.com/onflow/flow-cli/issues, 
and pasting the output as well as a description of the actions you took that resulted in this crash.

internal error: unexpected: invalid type produced without error
goroutine 1 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:26 +0x64
github.com/onflow/cadence/errors.NewUnexpectedErrorFromCause(...)
	github.com/onflow/cadence@v1.8.3/errors/errors.go:194
github.com/onflow/cadence/errors.NewUnexpectedError({0x1068ee72d?, 0x14001614a80?}, {0x0?, 0x107ad09e0?, 0x14001639980?})
	github.com/onflow/cadence@v1.8.3/errors/errors.go:188 +0x5c
github.com/onflow/cadence/sema.(*Checker).checkErrorsForInvalidExpressionTypes(0x140000440d8?, {0x107b25f00?, 0x14000974b40?}, {0x0, 0x0})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2611 +0x9c
github.com/onflow/cadence/sema.(*Checker).visitExpressionWithForceType(0x14000a4d450, {0x107b0bd20, 0x14001614a80}, {0x107af3210?, 0x1400162cb60?}, {0x0, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2565 +0xec
github.com/onflow/cadence/sema.(*Checker).visitExpression(...)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2458
github.com/onflow/cadence/sema.(*Checker).VisitExpression(0xf?, {0x107b0bd20?, 0x14001614a80?}, {0x107af3210?, 0x1400162cb60?}, {0x0?, 0x0?})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2453 +0x3c
github.com/onflow/cadence/sema.(*Checker).checkInvocationExpression(0x14000a4d450, 0x1400162cb60)
	github.com/onflow/cadence@v1.8.3/sema/check_invocation_expression.go:93 +0xb8
github.com/onflow/cadence/sema.(*Checker).VisitInvocationExpression(0x14000a4d450, 0x1400162cb60)
	github.com/onflow/cadence@v1.8.3/sema/check_invocation_expression.go:27 +0x24
github.com/onflow/cadence/ast.AcceptExpression[...]({0x107b0bcc0?, 0x1400162cb60}, {0x107b27f80, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:245 +0x21c
github.com/onflow/cadence/sema.(*Checker).visitExpressionWithForceType(0x14000a4d450, {0x107b0bcc0, 0x1400162cb60}, {0x107af31a0?, 0x14001616370?}, {0x0, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2563 +0xd0
github.com/onflow/cadence/sema.(*Checker).visitExpression(...)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2458
github.com/onflow/cadence/sema.(*Checker).VisitExpression(0x14001659dc8?, {0x107b0bcc0?, 0x1400162cb60?}, {0x107af31a0?, 0x14001616370?}, {0x0?, 0x0?})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2453 +0x3c
github.com/onflow/cadence/sema.(*Checker).visitVariableDeclarationValues(0x14000a4d450, 0x14001616370, 0x0)
	github.com/onflow/cadence@v1.8.3/sema/check_variable_declaration.go:57 +0x128
github.com/onflow/cadence/sema.(*Checker).VisitVariableDeclaration(0x14000a4d450, 0x14001616370)
	github.com/onflow/cadence@v1.8.3/sema/check_variable_declaration.go:27 +0x28
github.com/onflow/cadence/ast.AcceptStatement[...]({0x107b02dd0?, 0x14001616370}, {0x107b23060, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:151 +0x38c
github.com/onflow/cadence/sema.(*Checker).visitStatements(0x14000a4d450, {0x140001d0e00, 0x17, 0x104985cbc?})
	github.com/onflow/cadence@v1.8.3/sema/check_block.go:63 +0xdc
github.com/onflow/cadence/sema.(*Checker).visitFunctionBlock.func1()
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:485 +0x2c
github.com/onflow/cadence/sema.(*Checker).visitWithPostConditions(0x14000a4d450, {0x107af32f0, 0x1400110e150}, 0x0, {0x107b257f8, 0x10966c280}, {0x107ae11d8, 0x0}, 0x14000044ca8?)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:379 +0x1a8
github.com/onflow/cadence/sema.(*Checker).visitFunctionBlock(0x14000a4d450, 0x1400110e150, {0x107b257f8, 0x10966c280}, {0x107ae11d8, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:476 +0x134
github.com/onflow/cadence/sema.(*Checker).checkFunction.func1.2()
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:213 +0x34
github.com/onflow/cadence/sema.(*Checker).InNewPurityScope(0x14000a4d450, 0xc0?, 0x1096dfb40?)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:273 +0xe4
github.com/onflow/cadence/sema.(*Checker).checkFunction.func1(0x14000ab57c0)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:212 +0x198
github.com/onflow/cadence/sema.(*FunctionActivations).WithFunction(0x1400110e180, 0x14000ab1180, 0x2, 0x14000045080)
	github.com/onflow/cadence@v1.8.3/sema/function_activations.go:88 +0x144
github.com/onflow/cadence/sema.(*Checker).checkFunction(0x14000a4d450, 0x14000b9e360, 0x0, {0x1400163ef00?, 0x107b25f00?}, 0x14000ab1180, 0x1400110e150, 0x1, 0x0, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:187 +0x18c
github.com/onflow/cadence/sema.(*Checker).visitFunctionDeclaration(0x14000a4d450, 0x14001590120, {0x0?, 0xa3?, 0x65?}, 0x0)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:128 +0x3a4
github.com/onflow/cadence/sema.(*Checker).VisitFunctionDeclaration(0x1400162b440?, 0x14001eab6e0?, 0x5?)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:35 +0x2c
github.com/onflow/cadence/ast.AcceptDeclaration[...]({0x107b118e0?, 0x14001590120}, {0x107b14e20, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:71 +0x80
github.com/onflow/cadence/sema.(*Checker).CheckProgram(0x14000a4d450, 0x14001512240)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:462 +0x5dc
github.com/onflow/cadence/sema.(*Checker).Check.func1()
	github.com/onflow/cadence@v1.8.3/sema/checker.go:300 +0x50
github.com/onflow/cadence/sema.(*Checker).Check(0x14000a4d450)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:305 +0xb8
github.com/onflow/flow-cli/internal/cadence.(*linter).lintFile(0x140010e4100, {0x16b481dd3, 0x2b})
	github.com/onflow/flow-cli/internal/cadence/linter.go:125 +0x29c
github.com/onflow/flow-cli/internal/cadence.lintFiles(0x1049cd2b0?, {0x14000efd008, 0x73, 0x10627d3ac?})
	github.com/onflow/flow-cli/internal/cadence/lint.go:100 +0xac
github.com/onflow/flow-cli/internal/cadence.lint({0x14000efd008?, 0x0?, 0x0?}, {{0x0, 0x0}, {0x1068988af, 0x4}, {0x0, 0x0}, {0x0, ...}, ...}, ...)
	github.com/onflow/flow-cli/internal/cadence/lint.go:80 +0x30
github.com/onflow/flow-cli/internal/command.Command.AddToParent.func1(0x14000ec5300?, {0x14000efd008, 0x73, 0x73})
	github.com/onflow/flow-cli/internal/command/command.go:147 +0x46c
github.com/spf13/cobra.(*Command).execute(0x109675e00, {0x1400018e838, 0x73, 0x7c})
	github.com/spf13/cobra@v1.10.1/command.go:1019 +0x7bc
github.com/spf13/cobra.(*Command).ExecuteC(0x1400043d508)
	github.com/spf13/cobra@v1.10.1/command.go:1148 +0x350
github.com/spf13/cobra.(*Command).Execute(...)
	github.com/spf13/cobra@v1.10.1/command.go:1071
main.main()
	github.com/onflow/flow-cli/cmd/flow/main.go:139 +0xd80

[] []
map[device:map[arch:arm64 num_cpu:14] os:map[name:darwin] runtime:map[go_maxprocs:14 go_numcgocalls:13 go_numroutines:11 name:go version:go1.25.4] trace:map[span_id:806f0874ba47bafc trace_id:f9d2b8acb58eb7f2b949999f29edd09a]]
goroutine 1 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:26 +0x64
github.com/onflow/flow-cli/internal/command.initCrashReporting.func1(0x140010a8588, 0x1400109ea20)
	github.com/onflow/flow-cli/internal/command/command.go:355 +0x1d8
github.com/getsentry/sentry-go.(*Client).processEvent(0x14000ee4200, 0x140010a8588?, 0x1400109ea20, {0x107ad0e20, 0x140002b6580})
	github.com/getsentry/sentry-go@v0.36.2/client.go:679 +0x21c
github.com/getsentry/sentry-go.(*Client).CaptureEvent(...)
	github.com/getsentry/sentry-go@v0.36.2/client.go:468
github.com/getsentry/sentry-go.(*Client).RecoverWithContext(0x14000ee4200, {0x0, 0x0}, {0x10785dce0?, 0x1400163f4a0?}, 0x1079365e0?, {0x107ad0e20, 0x140002b6580})
	github.com/getsentry/sentry-go@v0.36.2/client.go:519 +0x18c
github.com/getsentry/sentry-go.(*Client).Recover(0x14000043ef8?, {0x10785dce0?, 0x1400163f4a0?}, 0x1049bed18?, {0x107ad0e20?, 0x140002b6580?})
	github.com/getsentry/sentry-go@v0.36.2/client.go:483 +0x80
github.com/getsentry/sentry-go.(*Hub).Recover(0x1400075a630, {0x10785dce0?, 0x1400163f4a0?})
	github.com/getsentry/sentry-go@v0.36.2/hub.go:322 +0xc0
github.com/getsentry/sentry-go.Recover()
	github.com/getsentry/sentry-go@v0.36.2/sentry.go:68 +0x40
panic({0x10785dce0?, 0x1400163f4a0?})
	runtime/panic.go:783 +0x120
github.com/onflow/cadence/sema.(*Checker).checkErrorsForInvalidExpressionTypes(0x140000440d8?, {0x107b25f00?, 0x14000974b40?}, {0x0, 0x0})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2611 +0xe0
github.com/onflow/cadence/sema.(*Checker).visitExpressionWithForceType(0x14000a4d450, {0x107b0bd20, 0x14001614a80}, {0x107af3210?, 0x1400162cb60?}, {0x0, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2565 +0xec
github.com/onflow/cadence/sema.(*Checker).visitExpression(...)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2458
github.com/onflow/cadence/sema.(*Checker).VisitExpression(0xf?, {0x107b0bd20?, 0x14001614a80?}, {0x107af3210?, 0x1400162cb60?}, {0x0?, 0x0?})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2453 +0x3c
github.com/onflow/cadence/sema.(*Checker).checkInvocationExpression(0x14000a4d450, 0x1400162cb60)
	github.com/onflow/cadence@v1.8.3/sema/check_invocation_expression.go:93 +0xb8
github.com/onflow/cadence/sema.(*Checker).VisitInvocationExpression(0x14000a4d450, 0x1400162cb60)
	github.com/onflow/cadence@v1.8.3/sema/check_invocation_expression.go:27 +0x24
github.com/onflow/cadence/ast.AcceptExpression[...]({0x107b0bcc0?, 0x1400162cb60}, {0x107b27f80, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:245 +0x21c
github.com/onflow/cadence/sema.(*Checker).visitExpressionWithForceType(0x14000a4d450, {0x107b0bcc0, 0x1400162cb60}, {0x107af31a0?, 0x14001616370?}, {0x0, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2563 +0xd0
github.com/onflow/cadence/sema.(*Checker).visitExpression(...)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2458
github.com/onflow/cadence/sema.(*Checker).VisitExpression(0x14001659dc8?, {0x107b0bcc0?, 0x1400162cb60?}, {0x107af31a0?, 0x14001616370?}, {0x0?, 0x0?})
	github.com/onflow/cadence@v1.8.3/sema/checker.go:2453 +0x3c
github.com/onflow/cadence/sema.(*Checker).visitVariableDeclarationValues(0x14000a4d450, 0x14001616370, 0x0)
	github.com/onflow/cadence@v1.8.3/sema/check_variable_declaration.go:57 +0x128
github.com/onflow/cadence/sema.(*Checker).VisitVariableDeclaration(0x14000a4d450, 0x14001616370)
	github.com/onflow/cadence@v1.8.3/sema/check_variable_declaration.go:27 +0x28
github.com/onflow/cadence/ast.AcceptStatement[...]({0x107b02dd0?, 0x14001616370}, {0x107b23060, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:151 +0x38c
github.com/onflow/cadence/sema.(*Checker).visitStatements(0x14000a4d450, {0x140001d0e00, 0x17, 0x104985cbc?})
	github.com/onflow/cadence@v1.8.3/sema/check_block.go:63 +0xdc
github.com/onflow/cadence/sema.(*Checker).visitFunctionBlock.func1()
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:485 +0x2c
github.com/onflow/cadence/sema.(*Checker).visitWithPostConditions(0x14000a4d450, {0x107af32f0, 0x1400110e150}, 0x0, {0x107b257f8, 0x10966c280}, {0x107ae11d8, 0x0}, 0x14000044ca8?)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:379 +0x1a8
github.com/onflow/cadence/sema.(*Checker).visitFunctionBlock(0x14000a4d450, 0x1400110e150, {0x107b257f8, 0x10966c280}, {0x107ae11d8, 0x0}, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:476 +0x134
github.com/onflow/cadence/sema.(*Checker).checkFunction.func1.2()
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:213 +0x34
github.com/onflow/cadence/sema.(*Checker).InNewPurityScope(0x14000a4d450, 0xc0?, 0x1096dfb40?)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:273 +0xe4
github.com/onflow/cadence/sema.(*Checker).checkFunction.func1(0x14000ab57c0)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:212 +0x198
github.com/onflow/cadence/sema.(*FunctionActivations).WithFunction(0x1400110e180, 0x14000ab1180, 0x2, 0x14000045080)
	github.com/onflow/cadence@v1.8.3/sema/function_activations.go:88 +0x144
github.com/onflow/cadence/sema.(*Checker).checkFunction(0x14000a4d450, 0x14000b9e360, 0x0, {0x1400163ef00?, 0x107b25f00?}, 0x14000ab1180, 0x1400110e150, 0x1, 0x0, 0x1)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:187 +0x18c
github.com/onflow/cadence/sema.(*Checker).visitFunctionDeclaration(0x14000a4d450, 0x14001590120, {0x0?, 0xa3?, 0x65?}, 0x0)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:128 +0x3a4
github.com/onflow/cadence/sema.(*Checker).VisitFunctionDeclaration(0x1400162b440?, 0x14001eab6e0?, 0x5?)
	github.com/onflow/cadence@v1.8.3/sema/check_function.go:35 +0x2c
github.com/onflow/cadence/ast.AcceptDeclaration[...]({0x107b118e0?, 0x14001590120}, {0x107b14e20, 0x14000a4d450})
	github.com/onflow/cadence@v1.8.3/ast/visitor.go:71 +0x80
github.com/onflow/cadence/sema.(*Checker).CheckProgram(0x14000a4d450, 0x14001512240)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:462 +0x5dc
github.com/onflow/cadence/sema.(*Checker).Check.func1()
	github.com/onflow/cadence@v1.8.3/sema/checker.go:300 +0x50
github.com/onflow/cadence/sema.(*Checker).Check(0x14000a4d450)
	github.com/onflow/cadence@v1.8.3/sema/checker.go:305 +0xb8
github.com/onflow/flow-cli/internal/cadence.(*linter).lintFile(0x140010e4100, {0x16b481dd3, 0x2b})
	github.com/onflow/flow-cli/internal/cadence/linter.go:125 +0x29c
github.com/onflow/flow-cli/internal/cadence.lintFiles(0x1049cd2b0?, {0x14000efd008, 0x73, 0x10627d3ac?})
	github.com/onflow/flow-cli/internal/cadence/lint.go:100 +0xac
github.com/onflow/flow-cli/internal/cadence.lint({0x14000efd008?, 0x0?, 0x0?}, {{0x0, 0x0}, {0x1068988af, 0x4}, {0x0, 0x0}, {0x0, ...}, ...}, ...)
	github.com/onflow/flow-cli/internal/cadence/lint.go:80 +0x30
github.com/onflow/flow-cli/internal/command.Command.AddToParent.func1(0x14000ec5300?, {0x14000efd008, 0x73, 0x73})
	github.com/onflow/flow-cli/internal/command/command.go:147 +0x46c
github.com/spf13/cobra.(*Command).execute(0x109675e00, {0x1400018e838, 0x73, 0x7c})
	github.com/spf13/cobra@v1.10.1/command.go:1019 +0x7bc
github.com/spf13/cobra.(*Command).ExecuteC(0x1400043d508)
	github.com/spf13/cobra@v1.10.1/command.go:1148 +0x350
github.com/spf13/cobra.(*Command).Execute(...)
	github.com/spf13/cobra@v1.10.1/command.go:1071
main.main()
	github.com/onflow/flow-cli/cmd/flow/main.go:139 +0xd80


@turbolent
Copy link
Copy Markdown
Member

Testing the linter in the latest version of Flow CLI (v2.15.1), it no longer crashes, so this PR should be good to go now

@turbolent turbolent force-pushed the vishal/add_cadence_linter branch from ca067a0 to 72e36e8 Compare March 19, 2026 19:51
@turbolent turbolent marked this pull request as ready for review March 19, 2026 20:11
@turbolent turbolent requested a review from a team as a code owner March 19, 2026 20:11
Copy link
Copy Markdown
Member

@Kay-Zee Kay-Zee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 3 spots where we see unused vars that look like they should be used. The best guess here is that they're left overs from our refactors, but I need a bit of help confirming that.

Comment thread cadence/contracts/FlowALPHealth.cdc Outdated
Comment thread cadence/contracts/FlowALPInterestRates.cdc Outdated
Comment thread cadence/contracts/FlowALPv0.cdc
Comment thread cadence/contracts/FlowALPv0.cdc
Comment thread Makefile
Comment thread Makefile

.PHONY: lint
lint:
find cadence/contracts -name "*.cdc" | xargs flow cadence lint \
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Kay-Zee why only lint contracts and not tests? 59af50b (this PR)

@turbolent turbolent requested a review from Kay-Zee April 13, 2026 23:21
@turbolent turbolent merged commit a69c7d3 into main Apr 14, 2026
1 check passed
@turbolent turbolent deleted the vishal/add_cadence_linter branch April 14, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants