func UnmarshalledSSZ
has a cyclomatic complexity of 59 with "critical" risk 33}
34
35// UnmarshalledSSZ unmarshalls serialized input.
36func UnmarshalledSSZ(t *testing.T, serializedBytes []byte, folderName string) (interface{}, error) { 37 var obj interface{}
38 switch folderName {
39 case "ExecutionPayload":
func UnmarshalBeaconState
has a cyclomatic complexity of 20 with "high" risk 99
100// UnmarshalBeaconState uses internal knowledge in the VersionedUnmarshaler to pick the right concrete BeaconState type,
101// then Unmarshal()s the type and returns an instance of state.BeaconState if successful.
102func (cf *VersionedUnmarshaler) UnmarshalBeaconState(marshaled []byte) (s state.BeaconState, err error) {103 forkName := version.String(cf.Fork)
104 switch fork := cf.Fork; fork {
105 case version.Phase0:
func Proto
has a cyclomatic complexity of 29 with "very-high" risk 346}
347
348// Proto converts the beacon block body to a protobuf object.
349func (b *BeaconBlockBody) Proto() (proto.Message, error) { 350 if b == nil {
351 return nil, nil
352 }
func Proto
has a cyclomatic complexity of 34 with "very-high" risk 164}
165
166// Proto converts the beacon block to a protobuf object.
167func (b *BeaconBlock) Proto() (proto.Message, error) { 168 if b == nil {
169 return nil, nil
170 }
func Proto
has a cyclomatic complexity of 34 with "very-high" risk 13)
14
15// Proto converts the signed beacon block to a protobuf object.
16func (b *SignedBeaconBlock) Proto() (proto.Message, error) { 17 if b == nil {
18 return nil, errNilBlock
19 }
func UnmarshalSSZ
has a cyclomatic complexity of 32 with "very-high" risk 942}
943
944// UnmarshalSSZ unmarshals the beacon block from its relevant ssz form.
945func (b *BeaconBlock) UnmarshalSSZ(buf []byte) error { 946 var newBlock *BeaconBlock
947 switch b.version {
948 case version.Phase0:
func UnmarshalSSZ
has a cyclomatic complexity of 32 with "very-high" risk 596}
597
598// UnmarshalSSZ unmarshals the signed beacon block from its relevant ssz form.
599func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error { 600 var newBlock *SignedBeaconBlock
601 switch b.version {
602 case version.Phase0:
func BuildSignedBeaconBlockFromExecutionPayload
has a cyclomatic complexity of 22 with "high" risk241
242// BuildSignedBeaconBlockFromExecutionPayload takes a signed, blinded beacon block and converts into
243// a full, signed beacon block by specifying an execution payload.
244func BuildSignedBeaconBlockFromExecutionPayload(245 blk interfaces.ReadOnlySignedBeaconBlock, payload interface{},
246) (interfaces.SignedBeaconBlock, error) {
247 if err := BeaconBlockIsNil(blk); err != nil {
func BuildSignedBeaconBlock
has a cyclomatic complexity of 23 with "high" risk163// BuildSignedBeaconBlock assembles a block.ReadOnlySignedBeaconBlock interface compatible struct from a
164// given beacon block and the appropriate signature. This method may be used to easily create a
165// signed beacon block.
166func BuildSignedBeaconBlock(blk interfaces.ReadOnlyBeaconBlock, signature []byte) (interfaces.SignedBeaconBlock, error) {167 pb, err := blk.Proto()
168 if err != nil {
169 return nil, err
func NewBeaconBlock
has a cyclomatic complexity of 23 with "high" risk 81}
82
83// NewBeaconBlock creates a beacon block from a protobuf beacon block.
84func NewBeaconBlock(i interface{}) (interfaces.ReadOnlyBeaconBlock, error) { 85 switch b := i.(type) {
86 case nil:
87 return nil, ErrNilObject
func NewSignedBeaconBlock
has a cyclomatic complexity of 23 with "high" risk 31)
32
33// NewSignedBeaconBlock creates a signed beacon block from a protobuf signed beacon block.
34func NewSignedBeaconBlock(i interface{}) (interfaces.SignedBeaconBlock, error) { 35 switch b := i.(type) {
36 case nil:
37 return nil, ErrNilObject
func IsEmptyExecutionData
has a cyclomatic complexity of 27 with "very-high" risk 987
988// IsEmptyExecutionData checks if an execution data is empty underneath. If a single field has
989// a non-zero value, this function will return false.
990func IsEmptyExecutionData(data interfaces.ExecutionData) (bool, error) { 991 if data == nil {
992 return true, nil
993 }
func RealPosition
has a cyclomatic complexity of 39 with "very-high" risk115
116// RealPosition denotes the position of the field in the beacon state.
117// The value might differ for different state versions.
118func (f FieldIndex) RealPosition() int {119 switch f {
120 case GenesisTime:
121 return 0
func String
has a cyclomatic complexity of 42 with "very-high" risk 26type FieldIndex int
27
28// String returns the name of the field index.
29func (f FieldIndex) String() string { 30 switch f {
31 case GenesisTime:
32 return "genesisTime"
func rootSelector
has a cyclomatic complexity of 51 with "critical" risk1164 return b == nil
1165}
1166
1167func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex) ([32]byte, error) {1168 _, span := trace.StartSpan(ctx, "beaconState.rootSelector")
1169 defer span.End()
1170 span.AddAttributes(trace.StringAttribute("field", field.String()))
func Copy
has a cyclomatic complexity of 31 with "very-high" risk 828}
829
830// Copy returns a deep copy of the beacon state.
831func (b *BeaconState) Copy() state.BeaconState { 832 b.lock.RLock()
833 defer b.lock.RUnlock()
834
func ComputeFieldRootsWithHasher
has a cyclomatic complexity of 49 with "very-high" risk 16)
17
18// ComputeFieldRootsWithHasher hashes the provided state and returns its respective field roots.
19func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]byte, error) { 20 ctx, span := trace.StartSpan(ctx, "ComputeFieldRootsWithHasher")
21 defer span.End()
22 if ctx.Err() != nil {
func ExpectedWithdrawals
has a cyclomatic complexity of 18 with "high" risk 99// break
100// validator_index = ValidatorIndex((validator_index + 1) % len(state.validators))
101// return withdrawals, partial_withdrawals_count
102func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, error) {103 if b.version < version.Capella {
104 return nil, 0, errNotSupported("ExpectedWithdrawals", b.version)
105 }
func ProcessRegistryUpdates
has a cyclomatic complexity of 16 with "high" risk 91// for index in activation_queue[:get_validator_churn_limit(state)]:
92// validator = state.validators[index]
93// validator.activation_epoch = compute_activation_exit_epoch(get_current_epoch(state))
94func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state.BeaconState, error) { 95 currentEpoch := time.CurrentEpoch(state)
96 vals := state.Validators()
97 var err error
func ProcessWithdrawals
has a cyclomatic complexity of 16 with "high" risk144// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
145// next_validator_index = ValidatorIndex(next_index % len(state.validators))
146// state.next_withdrawal_validator_index = next_validator_index
147func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) {148 expectedWithdrawals, _, err := st.ExpectedWithdrawals()
149 if err != nil {
150 return nil, errors.Wrap(err, "could not get expected withdrawals")
A function with high cyclomatic complexity can be hard to understand and maintain. Cyclomatic complexity is a software metric that measures the number of independent paths through a function. A higher cyclomatic complexity indicates that the function has more decision points and is more complex.
Functions with high cyclomatic complexity are more likely to have bugs and be harder to test. They may lead to reduced code maintainability and increased development time.
To reduce the cyclomatic complexity of a function, you can:
- Break the function into smaller, more manageable functions.
- Refactor complex logic into separate functions or classes.
- Avoid multiple return paths and deeply nested control expressions.
Bad practice
package main
import "log"
func fizzbuzzfuzz(x int) { // cc = 1
if x == 0 || x < 0 { // cc = 3 (if, ||)
return
}
for i := 1; i <= x; i++ { // cc = 4 (for)
switch i % 15 * 2 {
case 0: // cc = 5 (case)
countDiv3 += 1
countDiv5 += 1
log.Println("fizzbuzz")
break
case 3:
case 6:
case 9:
case 12: // cc = 9 (case)
countDiv3 += 1
log.Println("fizz")
break
case 5:
case 10: // cc = 11 (case)
countDiv5 += 1
log.Println("buzz")
break
default:
log.Printf("%d\n", x)
}
}
} // CC == 11; raises issues
Recommended
package main
import "log"
func fizzbuzz(x int) { // cc = 1
for i := 1; i <= x; i++ { // cc = 2 (for)
y := i%3 == 0
z := i%5 == 0
if y == z { // 3
if y == false { // 4
log.Printf("%d\n", i)
} else {
log.Println("fizzbuzz")
}
} else {
if y { // 5
log.Println("fizz")
} else {
log.Println("buzz")
}
}
}
} // CC == 5
Issue configuration
Cyclomatic complexity threshold can be configured using the
cyclomatic_complexity_threshold
(docs) in the
.deepsource.toml
config file.
Configuring this is optional. If you don't provide a value, the Analyzer will
raise issues for functions with complexity higher than the default threshold,
which is medium
(only raise issues for >15) for the Go Analyzer.
Here's the mapping of the risk category to the cyclomatic complexity score to help you configure this better:
Risk category | Cyclomatic complexity range | Recommended action |
---|---|---|
low | 1-5 | No action needed. |
medium | 6-15 | Review and monitor. |
high | 16-25 | Review and refactor. Recommended to add comments if the function is absolutely needed to be kept as it is. |
very-high. | 26-50 | Refactor to reduce the complexity. |
critical | >50 | Must refactor this. This can make the code untestable and very difficult to understand. |