Skip to content

v0.8.6 — No setup step: the first query indexes a checkout (--def answers in ~0.3-0.5 s while the rest indexes; CLI and editor share one index). Schema hover with db/structure.sql support; --dead finds unused RSpec lets, subjects, helpers and shared groups, and a shadowed tier; --refs by FILE:LINE. Store v59: trekr reindexes once after upgrading.

Choose a tag to compare

@dpep dpep released this 03 Oct 14:23
· 388 commits to main since this release
29aac66
  • --dead's output is the same on every run. A test-only constant's
    reason named its "first" test reference in the order the index's rows
    happened to come, which changed from run to run; it is the earliest by
    path and line now.
  • The first query in a repo indexes it. No trekr --index first, and no
    more not_indexed: --refs, --dead, --ancestors and cards wait for the
    whole index; a position (--def, FILE:LINE:COL) answers as soon as its
    file and the files and gems it names are read — with warming while the
    rest is read in the background — and a miss there waits for the rest
    rather than asking you to try again. A position the file alone answers
    — nothing under the cursor, a local, a symbol, the definition the cursor
    is on — answers at once, with no index. An index that takes more than a
    second says so once on stderr, and at a terminal shows a progress line that
    clears itself; stdout is still only the answer. Ctrl-C stops the wait, not
    the index. A checkout whose index an upgrade dropped, or one cut short, is
    indexed the same way. --status still only reports. An index that
    dies on the way — killed, or a full disk — ends the query with what it
    died of, and the next query finishes it.
  • One first index per checkout. A query, or a trekr --index, that finds
    another process's first index of the checkout under way (the language
    server's, another query's) waits for it instead of answering partial or
    indexing it a second time; --index says so on stderr. One left by a
    process that has since died is taken over at once, even when its pid now
    belongs to another program. The index under way reads next the file the
    waiting query asks about, or the editor has open — a --def behind the
    editor's first index, or the editor behind an agent's, answers in about a
    second rather than waiting for the whole checkout.
  • For scripts: --no-index or TREKR_NO_INDEX=1 keeps the old
    behaviour — answer from what is indexed, not_indexed (exit 2) where
    nothing is. A query whose index could not get the store's write lock in
    ten minutes answers as --index does: status: incomplete, exit 2.
  • Hover on a model shows its table. On an Active Record model's name, or
    any reference to it, the hover lists its table's columns — type as the
    schema spells it, null, default, the primary key first — and its indexes,
    linked to the table's line in db/schema.rb or db/structure.sql; a wide
    table shows twenty columns and says how many more. The table is worked out
    as Rails does: self.table_name, a namespace's table_name_prefix, and a
    single-table-inheritance subclass's base table, which the hover says it
    shares. An abstract class says it has no table. Nothing boots the app.
  • Hover on a column's attribute shows the column. post.title, title
    inside the model, or the column in db/schema.rb: "Column posts.title:
    string, not null, default """, linked to its line, where it said
    "Declared by schema". Completion's detail says the same.
  • Apps that keep db/structure.sql get their columns. An app that dumps
    its schema as SQL (Postgres or MySQL) had no attribute methods at all, so
    user.name.upcase resolved nothing; its columns are now read like
    db/schema.rb's, typed from their SQL types, for go to definition,
    references, hover, completion and --dead. When an app commits both
    files, the one Rails loads is read: db/schema.rb, unless
    config/application.rb sets schema_format = :sql. A view's columns are
    its select list's (a model backed by one says so, and how many it could
    not name); a table inheriting another has the parent's columns too; and a
    table in a schema the app's search path does not find is schema.table,
    a model's only through self.table_name = "schema.table".
  • A date column reads as Date, as ActiveRecord casts it, so
    post.published_on. offers Date's methods; it was typed Time.
  • An array column is an Array. t.bigint "tag_ids", array: true (or a
    Postgres bigint[]) types its reader as Array, not by its elements.
  • A column's definition is its own line. Go to definition on
    post.title lands on t.string "title" (or the column in
    db/structure.sql), not on create_table.
  • trekr Post --json carries table for a model: the table's name,
    where the schema declares it, its columns, primary key and indexes.
  • This changes what an index records (store v59): trekr reindexes once after upgrading.
  • --dead weighs an example group's own lets, subjects and defs.
    Each is read the way RSpec runs it: by its group's examples and those of
    the groups nested in it, by a hook or let of an enclosing group, which
    runs for them, by the body of a shared group included there (in any file,
    through it_behaves_like, include_examples or include_context), by
    super in an override, by is_expected and a bare should for a
    subject, and by what RSpec.configure adds to every group — a helper
    it includes, a shared group it includes by metadata, a config.before
    hook. One
    nothing reads is a row — kind: let, subject or method, with the
    group it is written in (group) and how many shared groups and helpers
    were read for it — unreferenced, or shadowed when every read lands on
    an override (overridden_by names them). let! runs for every example
    and is never listed. Every such row is lower, its caveat naming a
    risk where one was found (a name sent at runtime, a group macro trekr
    does not read, a string evaled): on mastodon's suite, run with every
    definition traced, every row was a let that never ran and it found 9 in
    10 of them, but suites held out from the rules each read a let some way
    they did not yet, so run the spec file after deleting one.
  • --dead lists a shared group nothing includes: a shared_examples or
    shared_context no it_behaves_like, include_examples or
    include_context names is a row, kind: shared_group, and its own
    lets are not listed apart from it. One written with metadata is
    convention-only, which the groups that match include.
  • shadowed, a new --dead tier: a method every call of whose name
    lands on an override in a subclass (an abstract raise NotImplementedError base), or a let every read of which an override in
    a nested group answers. overridden_by names the overrides. It was
    unreferenced, with nothing to say why the name looked used.
  • A group's def is no longer unreferenced while it is called. It was
    weighed against an owner no call resolves to.
  • --refs FILE:LINE[:COL] lists the references of what is at a
    position. On a let, subject or group def (or a read of one), every
    read, tiered, with from saying where it was found (group,
    nested_group, enclosing_group, shared_group, includer, helper,
    super, subject); --dead finds the same reads. On a method's
    definition or a call of it, the method's references, as --refs Owner#method lists them; on a class, module or constant, its mentions,
    as --refs Name lists them. The let keyword of let(:x) means the
    let it defines, as Find References in the editor reads it.
  • Find References on a let or subject in the editor lists the same
    reads, a shared group's body in another file included.
  • Go to definition on a call in a shared group's body that the body does
    not define lands on each including group's let, subject or def of
    the name — one answer, or one per includer (resolved_via: includer).
    It was residue. A helper RSpec.configure includes in every group is
    the answer only for the includers that define nothing of the name.