Git Product home page Git Product logo

todos's Introduction

todos

unit tests codecov Go Report Card FOSSA Status OpenSSF Scorecard SLSA 3

Parse out TODOs, FIXMEs, BUGs and HACKs from your code.

todos screenshot

This repo contains the following tools for dealing with TODOs in code.

  • todos CLI: searches for TODO comments in code and prints them in various formats.

See the FAQ for more info on the philosophy behind the project.

TODO comment format

"TODO" comments are comments in code that mark a task that is intended to be done in the future.

For example:

// TODO(some label or reference): Update this code.

TODO comment type variants

There a few veriants of this type of comment thare are in wide use.

  • TODO: A general TODO comment indicating something that is to be done in the future.
  • FIXME: Something that is broken that needs to be fixed in the code.
  • BUG: A bug in the code that needs to be fixed.
  • HACK: This code is a "hack"; a hard to understand or brittle piece of code. It could use a cleanup.
  • XXX: Danger! Similar to "HACK". Modifying this code is dangerous. It
  • COMBAK: Something you should "come back" to.

TODO comment examples

TODO comments can include some optional metadata. Here are some examples:

  • A naked TODO comment.

    // TODO
  • A TODO comment with an explanation message

    // TODO: Do something.
  • A TODO comment with a linked bug or issue and optional message

    // TODO(github.com/ianlewis/todos/issues/8): Do something.
  • A TODO comment with a username and optional message. This type is discouraged as it links the issue to a specific developer but can be helpful temporarily when making changes to a PR. Linking to issues is recommended for permanent comments.

    // TODO(ianlewis): Do something.

Use Cases

Tracking TODOs in code can help you have a cleaner and heathier code base. Here are some basic use cases.

Finding TODOs in your code

You can use the todos CLI to find TODO comments in your code and print them out. Running it will search the directory tree starting at the current directory by default.

$ todos
main.go:27:// TODO(#123): Return a proper exit code.
main.go:28:// TODO(ianlewis): Implement the main method.

In order for the comments to be more easily parsed keep in mind the following:

  • Spaces between the comment start and 'TODO' is optional (e.g. //TODO: some comment)
  • TODOs should have a colon if a message is present so it can be distingished from normal comments.
  • TODOs can be prefixed with @ (e.g. // @TODO: comment)
  • Comments can be on the same line with other code (e.g. x = f() // TODO: call f
  • Line comment start sequences can be repeated (e.g. //// TODO: some comment)
  • Only the single line where the TODO occurs is printed for multi-line comments.
  • TODO,FIXME,BUG,HACK,XXX,COMBAK are supported by default. You can change this with the --todo-types flag.

See the todos CLI documentation for more info.

Re-open prematurely closed issues

Sometimes issues get closed before all of the relevant code is updated. You can use todos to re-open issues where TODO comments that reference the issue still exist in the code with the ianlewis/todo-issue-reopener action.

// TODO(#123): Still needs work.

See ianlewis/todo-issue-reopener for more information.

todos CLI tool

The todos CLI scans files in a directory and prints any "TODO" comments it finds in various formats.

Install todos

There are two methods for installing todos.

Install todos from a release

Download the slsa-verifier and verify it's checksum:

curl -sSLo slsa-verifier https://github.com/slsa-framework/slsa-verifier/releases/download/v2.3.0/slsa-verifier-linux-amd64 && \
echo "ea687149d658efecda64d69da999efb84bb695a3212f29548d4897994027172d  slsa-verifier" | sha256sum -c - && \
chmod +x slsa-verifier

Download and verify the todos CLI binary and verify it's provenance:

curl -sSLo todos https://github.com/ianlewis/todos/releases/download/v0.8.0/todos-linux-amd64 && \
curl -sSLo todos.intoto.jsonl https://github.com/ianlewis/todos/releases/download/v0.8.0/todos-linux-amd64.intoto.jsonl && \
./slsa-verifier verify-artifact todos --provenance-path todos.intoto.jsonl --source-uri github.com/ianlewis/todos --source-tag v0.8.0 && \
chmod +x todos && \
sudo cp todos /usr/local/bin

Install todos from source

If you already have Go 1.20+ you can install the latest version using go install:

go install github.com/ianlewis/todos/internal/cmd/todos

Usage

Simply running todos will search TODO comments starting in the current directory. By default it ignores files that are in "VCS" directories (such as.git or .hg) and vendored code (such as node_modules, vendor, and third_party).

Here is an example running in a checkout of the Kubernetes codebase.

kubernetes$ todos
build/common.sh:346:# TODO: remove when 17.06.0 is not relevant anymore
build/lib/release.sh:148:# TODO: Docker images here
cluster/addons/addon-manager/kube-addons.sh:233:# TODO: Remove the first command in future release.
cluster/addons/calico-policy-controller/ipamblock-crd.yaml:41:# TODO: This nullable is manually added in. We should update controller-gen
cluster/addons/dns/kube-dns/kube-dns.yaml.base:119:# TODO: Set memory limits when we've profiled the container for large
cluster/addons/dns/kube-dns/kube-dns.yaml.in:119:# TODO: Set memory limits when we've profiled the container for large
cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml:120:# TODO(random-liu): Remove this after cri container runtime rolls out.
cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml:244:# TODO(random-liu): Keep this for compatibility, remove this after
cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml:345:# TODO(instrumentation): Reconsider this workaround later.
cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml:135:# TODO(random-liu): Remove this after cri container runtime rolls out.
cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml:259:# TODO(random-liu): Keep this for compatibility, remove this after
cluster/addons/fluentd-gcp/fluentd-gcp-configmap.yaml:362:# TODO(instrumentation): Reconsider this workaround later.
...

Running on sub-directories or files

You can run todos on sub-directories or individual files by passing them on the command line.

kubernetes$ todos hack/ Makefile
hack/e2e-internal/e2e-cluster-size.sh:32:#TODO(colhom): spec and implement federated version of this
hack/ginkgo-e2e.sh:118:# TODO(kubernetes/test-infra#3330): Allow NODE_INSTANCE_GROUP to be
hack/lib/golang.sh:456:# TODO: This symlink should be relative.
hack/lib/protoc.sh:119:# TODO: switch to universal binary when updating to 3.20+
hack/lib/util.sh:337:# TODO(lavalamp): Simplify this by moving pkg/api/v1 and splitting pkg/api,
hack/lib/version.sh:74:# TODO: We continue calling this "git version" because so many
hack/make-rules/test.sh:61:# TODO: This timeout should really be lower, this is a *long* time to test one
hack/module-graph.sh:19:# TODO: Containerize the script to remove dependency issues with go mod and dot.
hack/update-codegen.sh:420:# TODO: it might be better in the long term to make peer-types explicit in the
hack/verify-api-groups.sh:96:# TODO: Remove this package completely and from this list
hack/verify-e2e-test-ownership.sh:20:# TODO: these two can be dropped if KubeDescribe is gone from codebase
hack/verify-external-dependencies-version.sh:39:# TODO: revert sed hack when zetigeist respects CLICOLOR/ttys
hack/verify-licenses.sh:101:# TODO: Remove this workaround check once PR https://github.com/google/go-licenses/pull/110 is merged
Makefile:313:# TODO(thockin): Remove this in v1.29.
Makefile:504:#TODO: make EXCLUDE_TARGET auto-generated when there are other files in cmd/

Running in GitHub Actions

If run as part of a GitHub action todos will function much like a linter and output GitHub workflow commands which will add check comments to PRs.

kubernetes$ todos -o github Makefile
::warning file=Makefile,line=313::# TODO(thockin): Remove this in v1.29.
::warning file=Makefile,line=504::#TODO: make EXCLUDE_TARGET auto-generated when there are other files in cmd/

An example workflow might look like the following. todos will output GitHub Actions workflow commands by default when running on GitHub Actions:

on:
  pull_request:
    branches: [main]
  workflow_dispatch:

permissions: {}

jobs:
  todos:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v3
      - name: install todos
        run: |
          curl -sSLo slsa-verifier https://github.com/slsa-framework/slsa-verifier/releases/download/v2.3.0/slsa-verifier-linux-amd64 && \
          echo "ea687149d658efecda64d69da999efb84bb695a3212f29548d4897994027172d  slsa-verifier" | sha256sum -c - && \
          chmod +x slsa-verifier

          curl -sSLo todos https://github.com/ianlewis/todos/releases/download/v0.8.0/todos-linux-amd64 && \
          curl -sSLo todos.intoto.jsonl https://github.com/ianlewis/todos/releases/download/v0.8.0/todos-linux-amd64.intoto.jsonl && \
          ./slsa-verifier verify-artifact todos --provenance-path todos.intoto.jsonl --source-uri github.com/ianlewis/todos --source-tag v0.8.0 && \
          rm -f slsa-verifier && \
          chmod +x todos

      - name: run todos
        run: |
          ./todos .

Outputting JSON

todos can produce output in JSON format for more complicated processing.

kubernetes$ todos -o json
{"path":"build/common.sh","type":"TODO","text":"# TODO: remove when 17.06.0 is not relevant anymore","label":"","message":"remove when 17.06.0 is not relevant anymore","line":346,"comment_line":346}
{"path":"build/lib/release.sh","type":"TODO","text":"# TODO: Docker images here","label":"","message":"Docker images here","line":148,"comment_line":148}
{"path":"cluster/addons/addon-manager/kube-addons.sh","type":"TODO","text":"# TODO: Remove the first command in future release.","label":"","message":"Remove the first command in future release.","line":233,"comment_line":233}
{"path":"cluster/addons/calico-policy-controller/ipamblock-crd.yaml","type":"TODO","text":"# TODO: This nullable is manually added in. We should update controller-gen","label":"","message":"This nullable is manually added in. We should update controller-gen","line":41,"comment_line":41}
{"path":"cluster/addons/dns/kube-dns/kube-dns.yaml.base","type":"TODO","text":"# TODO: Set memory limits when we've profiled the container for large","label":"","message":"Set memory limits when we've profiled the container for large","line":119,"comment_line":119}
{"path":"cluster/addons/dns/kube-dns/kube-dns.yaml.in","type":"TODO","text":"# TODO: Set memory limits when we've profiled the container for large","label":"","message":"Set memory limits when we've profiled the container for large","line":119,"comment_line":119}
{"path":"cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml","type":"TODO","text":"# TODO(random-liu): Remove this after cri container runtime rolls out.","label":"random-liu","message":"Remove this after cri container runtime rolls out.","line":120,"comment_line":120}
{"path":"cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml","type":"TODO","text":"# TODO(random-liu): Keep this for compatibility, remove this after","label":"random-liu","message":"Keep this for compatibility, remove this after","line":244,"comment_line":244}
{"path":"cluster/addons/fluentd-gcp/fluentd-gcp-configmap-old.yaml","type":"TODO","text":"# TODO(instrumentation): Reconsider this workaround later.","label":"instrumentation","message":"Reconsider this workaround later.","line":345,"comment_line":345}
...
kubernetes$ # Get all the unique files with TODOs that Tim Hockin owns.
kubernetes$ todos -o json | jq -r '. | select(.label = "thockin") | .path' | uniq

Supported Languages

See SUPPORTED_LANGUAGES.md.

Related projects

FAQ

Why use this?

Tracking TODOs in code can help you have a cleaner and heathier code base.

  1. It can help you realize when issues you thought were complete actually require some additional work (See actions/issue-reopener).
  2. It makes it easier for contributors to find areas of the code that need work.
  3. It makes it easier for contributors to find the relevant code for an issue.

Why not just use grep?

grep is an amazing and blazingly fast tool. However, there are a few reasons why you might use todos.

  1. grep doesn't have much knowledge of code and languages so it's difficult to differentiate between comments and code. todos will ignore matches in code and only prints TODOs found it comments. It also ignores matches that occur in strings.
  2. grep doesn't know about repository structure. It doesn't have inherant knowledge of VCS directories (e.g. .git) or vendored dependencies. It can't make use of .gitignore or other hints.
  3. todos will parse TODO comments and can output in different formats such as JSON. This gives users an easy way to search for TODOs with their username, or with a specific issue number.

Contributing

See CONTRIBUTING.md for contributor documentation.

todos's People

Contributors

dependabot[bot] avatar ianlewis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

fossabot

todos's Issues

Combine pre-submit workflows

Combine pre-submit workflows into a single workflow.yml since the all have the same triggers. That way a single status badge can be used for the README

Bugs processing dotfiles

A number of scanning bugs come up when running todos on my dotfiles. Need to investigate and fix those bugs.

Windows hidden file test failure

https://github.com/ianlewis/todos/actions/runs/5167637338/jobs/9308650495

--- FAIL: Test_isHidden/some\path\.foo.bar#01 (0.00s)
panic: open C:\Users\RUNNER~1\AppData\Local\Temp\utils_windows_test170354236\some\path\.foo.bar: The system cannot find the path specified. [recovered]
	panic: open C:\Users\RUNNER~1\AppData\Local\Temp\utils_windows_test170354236\some\path\.foo.bar: The system cannot find the path specified.

goroutine 432 [running]:
testing.tRunner.func1.2({0x1239660, 0xc00123a630})
	C:/hostedtoolcache/windows/go/1.20.4/x64/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
	C:/hostedtoolcache/windows/go/1.20.4/x64/src/testing/testing.go:1529 +0x39f
panic({0x1239660, 0xc00123a630})
	C:/hostedtoolcache/windows/go/1.20.4/x64/src/runtime/panic.go:884 +0x213
github.com/ianlewis/todos/internal/testutils.Check(...)
	D:/a/todos/todos/internal/testutils/utils.go:20
github.com/ianlewis/todos/internal/cmd/todos/walker.Test_isHidden.func1(0xc0012a1040)
	D:/a/todos/todos/internal/cmd/todos/walker/utils_windows_test.go:[100](https://github.com/ianlewis/todos/actions/runs/5167500382/jobs/9308416258?pr=49#step:4:101) +0x29e
testing.tRunner(0xc0012a[104](https://github.com/ianlewis/todos/actions/runs/5167500382/jobs/9308416258?pr=49#step:4:105)0, 0xc00142b760)
	C:/hostedtoolcache/windows/go/1.20.4/x64/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
	C:/hostedtoolcache/windows/go/1.20.4/x64/src/testing/testing.go:1629 +0x3ea

Command to parse out and print TODOs

The command should support walking a directory tree and parsing supported files, as well as just taking raw text over stdin with maybe a language hint.

Walk a directory:

$ todos ./dir

Test fixture for walker

Add a testutils package under internal/walker which facilitates creating a test directory with code and cleaning it up for testing.

Skip symbolic links that point to a non-existent file

panic: open .remarkrc: no such file or directory

goroutine 1 [running]:
main.main.func1({0xc0000caa00, 0x9}, {0xb?, 0x9?}, {0xc000093d78?, 0x49f33d?})
        github.com/ianlewis/todos/internal/cmd/todos/main.go:99 +0x357
io/fs.walkDir({0x5d04e0, 0xc00021ce50}, {0xc0000caa00, 0x9}, {0x5d0948, 0xc0000b3340}, 0xc000093f50)
        io/fs/walk.go:73 +0x78
io/fs.walkDir({0x5d04e0, 0xc00021ce50}, {0x5ce500, 0x1}, {0x5d0910, 0xc00021ce60}, 0xc000093f50)
        io/fs/walk.go:95 +0x2e6
io/fs.WalkDir({0x5d04e0, 0xc00021ce50}, {0x5ce500, 0x1}, 0xc000093f50)
        io/fs/walk.go:122 +0xde
main.main()
        github.com/ianlewis/todos/internal/cmd/todos/main.go:95 +0x2c5

Github issue reopener

Github action to re-open issues that have been closed but still have TODOs referring to them

Add --version flag

Add --version flag to show the version. Automatically update the version for releases.

Fuzzing

Some fuzz testing of the app would be nice to catch potential issues.

Doc on why the project exists

Answer some questions users might have.

  • Why is the project needed?
    • Tracking whether issues are really complete
    • Making it easier for contributors to find the relevant code for an issue
  • Why not just use grep?
    • Grep doesn't know about code or project directory structure
      • Files ignored by repository (.gitignore)
      • Binary files
      • Can't differentiate between code and comments
    • Maybe include a sample grep command in case they really want to use it

Print single line from multi-line comments

Currently if a multi-line comment has a TODO in it, the comment is printed in its entirety. Instead only the line containing the TODO should be printed so that each TODO only creates one line of output.

Support file encodings other than UTF-8

Currently code is assumed to be utf-8 and may fail when reading code.

  • Detect encoding of files.
  • Convert files to utf-8 on the fly before scanning for TODOs

Github TODO Commenter

Github Action/bot that comments on issues with links to code that refers to them.

Ideally this happens when commits are pushed much like the links that get added due to "fixes" style references in commit messages.

Github review bot

Review bot that

  • blocks PRs from being merged if they have FIXME comments
  • blocks PRs from being merged if they have TODOs without an issue attached

Improve scanner tests

The scanner package should have more tests.

  • Test where single line comment and multi-line comment start have overlapping characters.
  • Test where single line comment and string types overlap.
  • Test where multi-line comment and string types overlap.

Installation docs

Add docs on how to install from releases & how to verify provenance.

Concurrency support

Parse files concurrently.

Output should still be shown deterministically so that TODOs for the same file and directories are shown together in sequence.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.