Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add nakedefer linter #3282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
rawen17 wants to merge 4 commits into golangci:master
base: master
Choose a base branch
Loading
from rawen17:adddefer
Open

feat: add nakedefer linter #3282

rawen17 wants to merge 4 commits into golangci:master from rawen17:adddefer

Conversation

@rawen17
Copy link

@rawen17 rawen17 commented Oct 7, 2022
edited
Loading

nakedefer is a linter that finds defer functions which return anything.
https://github.com/GaijinEntertainment/go-nakedefer

Copy link

boring-cyborg bot commented Oct 7, 2022

Hey, thank you for opening your first Pull Request !

Copy link

CLAassistant commented Oct 7, 2022
edited
Loading

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ ldez
❌ rawen17
You have signed the CLA already but the status is still pending? Let us recheck it.

Copy link
Member

ldez commented Oct 7, 2022
edited
Loading

In order for a pull request adding a linter to be reviewed, the linter and the PR must follow some requirements.

Pull Request Description

  • It must have a link to the linter repository.
  • It must provide a short description about the linter.

Linter

  • It must not be a duplicate of another linter or a rule of a linter. (the team will help to verify that)
  • It must have a valid license and the file must contain the required information by the license, ex: author, year, etc.
  • The linter repository must have a CI and tests.
  • It must use go/analysis.
  • It must have a valid tag, ex: v1.0.0, v0.1.0.
  • It must not contain init().
  • It must not contain panic(), log.fatal(), os.exit(), or similar.
  • It must not have false positives/negatives. (the team will help to verify that)
  • It must have tests inside golangci-lint.

The Linter Tests Inside Golangci-lint

  • They must have at least one std lib import.
  • They must work with T=<name of the linter test file>.go make test_linters. (the team will help to verify that)

.golangci.reference.yml

  • The linter must be added to the list of available linters (alphabetical case-insensitive order).
    • enable and disable options
  • If the linter has a configuration, the exhaustive configuration of the linter must be added (alphabetical case-insensitive order)
    • The values must be different from the default ones.
    • The default values must be defined in a comment.
    • The option must have a short description.

Others Requirements

  • The files (tests and linter) inside golangci-lint must have the same name as the linter.
  • The .golangci.yml of golangci-lint itself must not be edited and the linter must not be added to this file.
  • The linters must be sorted in the alphabetical order (case-insensitive) in the Manager.GetAllSupportedLinterConfigs(...) and .golangci.reference.yml.
  • The load mode (WithLoadMode(...)):
    • if the linter doesn't use types: goanalysis.LoadModeSyntax
    • goanalysis.LoadModeTypesInfo required WithLoadForGoAnalysis() in the Manager.GetAllSupportedLinterConfigs(...)
  • The version in WithSince(...) must be the next minor version (v1.X.0) of golangci-lint.

Recommendations

  • The linter should not use SSA. (currently, SSA does not support generics)
  • The linter repository should have a readme and linting.
  • The linter should be published as a binary. (useful to diagnose bug origins)

The golangci-lint team will edit this comment to check the boxes before and during the review.

This checklist does not imply that we will accept the linter.

Copy link
Member

ldez commented Oct 7, 2022

Hello,

maybe I have missed something: why only defer that uses a function returning a function is a problem?

IMO using a function that returns something (not only a function) for a defer is a problem.

@ldez ldez added linter: new Support new linter waiting for: contributor feedback Requires additional feedback labels Oct 7, 2022
Copy link
Contributor

xobotyi commented Oct 10, 2022

@ldez sometimes we're using factory for deferred functions, this linter tracks situation when deferred function returns a function and ensures that returned function is invoked, i.e. defer deferredFnFactory() would raise an error

Copy link
Contributor

xobotyi commented Oct 10, 2022
edited
Loading

Overall you're right, and maybe we have to make the linter stricter🤔

ldez reacted with thumbs up emoji

Copy link
Author

rawen17 commented Oct 11, 2022

Hello!
I\ve fixed this problem. Now defer linter сhecks that deferred call does not return anything.

Copy link
Member

ldez commented Oct 11, 2022

@rawen17 you have to sign the CLA #3282 (comment)

Copy link
Author

rawen17 commented Oct 11, 2022
edited by ldez
Loading

I've signed it already

Copy link
Member

ldez commented Oct 11, 2022

vbuianov seems not to be a GitHub user.

The email that you are using to commit is not set up in your GitHub account, so you haven't signed.

Copy link
Author

rawen17 commented Oct 11, 2022
edited by ldez
Loading

Sorry, now is signed

@ldez ldez self-requested a review October 11, 2022 13:05
@ldez ldez removed the waiting for: contributor feedback Requires additional feedback label Oct 11, 2022
Copy link
Contributor

@rawen17, please, select more specific naming.

defer does not reflect the essence of the linter, as well as messages from it.

Moreover, it would be great to see among the examples something less abstract and closer to real life. Now it raise more questions than answers.

E.g., why is it invalid?

func funcDeferAnonymousReturnIntAndErr() {
	defer func() (int, error) { // want "deferred call should not return anything"
		return 1, nil
	}()
}

If you explain more clearly the reason of the linter, I can help with the name.

Thanks 👍

@ldez ldez added the waiting for: contributor feedback Requires additional feedback label Oct 17, 2022
Copy link
Author

rawen17 commented Oct 18, 2022
edited
Loading

@Antonboom, hi!
This linter was been created to prevent cases when defer functions return any types
There are two cases:

  • defer function doesn't return anything - valid for linter
  • defer function returns one or more types - invalid for linter
    In this case there is a function which has defer anonymous function inside and it returns two types (int and error)
    That's why it is invalid for linter
func funcDeferAnonymousReturnIntAndErr() {
	defer func() (int, error) { // want "deferred call should not return anything"
		return 1, nil
	}()
}

May be i misunderstood your question
If you mean why defer function must not return anything
i think, it is best practice because it error-prone cases

Copy link
Contributor

Antonboom commented Oct 18, 2022
edited
Loading

Okay, does the linter ignore io.Closer and other functions from popular interfaces that are usually deferred?

I propose something like:

  • nakedefer (like nakedret)
  • novaluedefer (like nonamedreturn)
  • puredefer, cleandefer, etc.

Copy link
Member

Okay, does the linter ignore io.Closer and other functions from popular interfaces that are usually deferred?

Curious about this as well. If not, I see a lot of this pattern incoming:

defer func() {
 _, _ = whatIActuallyWanted()
}()

Copy link
Author

rawen17 commented Oct 19, 2022

In test/testdata/defer.go there are 2 examples

funcReturnErr - can be like io.Closer method Close which returns error

  1. Valid for linter
func funcDeferNotReturnAnyType2() {
	defer func() {
		_ = funcReturnErr()
	}()
}
  1. Invalid for linter
func funcDeferReturnErr() {
	defer funcReturnErr() // want "deferred call should not return anything"
}

@rawen17 rawen17 changed the title (削除) feat: add defer linter (削除ここまで) (追記) feat: add nakedefer linter (追記ここまで) Oct 24, 2022
Copy link
Author

rawen17 commented Oct 24, 2022

Change name linter 'defer' to 'nakedefer'
Add 'exclude' in config to exclude function names

Antonboom reacted with thumbs up emoji

Copy link
Member

ldez commented Oct 24, 2022

@rawen17 can you rebase and fix the conflict?

Copy link
Member

ldez commented Oct 24, 2022

@rawen17 why did you close the PR?

Copy link
Author

rawen17 commented Oct 24, 2022

No, it is my fault, i will try fix it
Can i open this PR again?

Copy link
Member

ldez commented Oct 24, 2022
edited
Loading

yes you can reopen this PR, but you need to add commits 😉

@rawen17 rawen17 reopened this Oct 24, 2022
@rawen17 rawen17 requested review from alexandear and removed request for ldez October 25, 2022 13:20
Copy link
Author

rawen17 commented Nov 11, 2022

@ldez Hello!
Can you please review this PR and tell me what i have to do for your approval?

@ldez ldez self-requested a review November 11, 2022 10:07
@ldez ldez added waiting for: contributor feedback Requires additional feedback and removed waiting for: contributor feedback Requires additional feedback labels Nov 11, 2022
@ldez ldez force-pushed the adddefer branch 2 times, most recently from 83cada1 to d7e6791 Compare January 21, 2023 13:00
@ldez ldez removed the waiting for: contributor feedback Requires additional feedback label Jan 21, 2023
Copy link
Member

ldez commented Feb 27, 2023

Sorry for the late reply.

I share the point of view of @bombsimon maybe it can be a good idea to add io\.Close as default (only if no user configuration)

@ldez ldez added the waiting for: contributor feedback Requires additional feedback label Feb 27, 2023
Copy link
Contributor

Antonboom commented Oct 1, 2023
edited
Loading

@xobotyi @rawen17 hi!

Could you please add default value for -e flag?
See comments above.

I run linter on large code base and receive warnings about:

defer t.Stop() // *time.Timer
defer response.Body.Close()
defer db.Close() // *pg.DB

P.S. It's also cool to not ignore README badges like "Go Report", "CI Build Status", etc.

P.P.S. Could be helpful

  • golangci-lint config
--exclude-use-default Use or not use default excludes:
 # EXC0001 errcheck: Almost all programs ignore errors on these functions and in most cases it's ok
 - Error return value of .((os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv). is not checked 

@alexandear alexandear removed their request for review November 21, 2023 22:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@alexandear alexandear alexandear requested changes

@ldez ldez Awaiting requested review from ldez

Assignees

No one assigned

Labels

linter: new Support new linter waiting for: contributor feedback Requires additional feedback

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

AltStyle によって変換されたページ (->オリジナル) /