Skip to content

Latest commit

聽

History

History
219 lines (153 loc) 路 4.5 KB

agents.md

File metadata and controls

219 lines (153 loc) 路 4.5 KB

Development

Documentation

Prefer consulting local sources for information about Rust dependencies.

Run cargo dep NAME to find the source directory of a dependency:

$ cargo dep serde
/Users/rodarmor/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/serde-1.0.228/

Dependencies

Add dependencies with cargo add instead of manually editing Cargo.toml.

Editing

Prefer the edit tool over scripts to make changes to a handful of known sites.

Imports

Don't rename imports in use statements.

use std::io::Result as IoResult;

fn foo() -> IoResult<()>;
use std::io::Result as IoResult;

fn read() -> io::Result<()>;

Imports which are unambiguously named and common should go in the top-level module and be inherited by child modules with use super::*.

Style

Do not write comments or documentation, or modify existing comments or documentation. Both will be added by the user as necessary.

Don't create mutable variables that are initialized in a conditional:

let mut foo = None;

if bar {
  foo = Some("hello");
}

Instead, create an immutable variable initialized with an if/else:

let foo = if bar {
  Some("hello")
} else {
  None
};

When converting a value, shadowing the previous variable is often ideal. The type system prevents confusing the two values, and shadowing the previous variable prevents it from being unintentionally used later:

let name_string = name.to_string();
let name = name.to_string();

Prefer turbofish over type ascription:

let foo: T = foo.parse().unwrap();
let bar: Vec<u8> = foo.into_iter().collect();
let foo = foo.parse::<T>().unwrap();
let bar = foo.into_iter().collect::<Vec<u8>>();

Use type inference where possible:

let bar = foo.into_iter().collect();
let bar = foo.into_iter().collect::<Vec<u8>>();

Don't use _ placeholders:

let bar = foo.into_iter().collect::<Vec<u8>>();
let bar = foo.into_iter().collect::<Vec<_>>();

Testing

Testing is white-box style. Write tests needed to exercise the implementation. Add only the minimum number of tests needed to cover new and changed code.

Do not perform manual testing. All testing should be done via unit and integration tests.

Headless browser testing is slow. Do not use a headless browser for manual testing or reproducing issues unless asked.

Individual tests should use as little code as possible to exercise the feature under test.

Tests should use foo, bar, and similar placeholders in strings to make clear that the values themselves are not significant.

std::fs::write("file.txt"), "contents").unwrap();
std::fs::write("foo"), "bar").unwrap();

Prefer asserting the entire contents of values:

assert!(path.ends_with("foo/bar"));
assert_eq!(path, "/home/user/foo/bar");

Prefer asserting error messages exactly:

assert!(Regex::new("I/O failed").unwrap().is_match(error));
assert_eq!(message, "error: I/O failed at `foo/bar/baz`");

If nondeterminism forces you to match an error message with a regular expression, always match the entire message:

assert!(Regex::new("bad thing").unwrap().is_match(error));
assert!(Regex::new("^error: bad thing ID [0-9]+$").unwrap().is_match(error));

Prefer matching complete patterns:

assert_matches!(result, Err(Error::Foo { .. }));
assert_matches!(result, Err(Error::Foo { message: "bar" }));

Git

Do not commit changes, amend history, or stage or unstage changes, or use the stash unless explicitly asked.

Do not push commits, create issues, open PRs, or mutate state on GitHub unless explicitly asked.

The user may stage or unstage changes as he reviews your changes, so expect changes to be staged and unstaged as you work.

Terminology

Prefer "whitelist" and "blacklist" instead of "allowlist" and "blocklist".

Tips

If you need a constant for a test, but the value of that constant is hard to calculate, assert equality with a dummy value:

assert_eq!(complicated_calculation(), "");

Then get the correct value from the error message and insert it:

assert_eq!(
  complicated_calculation(),
  "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
);

Avoid lossy conversions from invalid UTF-8 bytes to strings.