Harsh Chokshi
hchok@meta.com
90d · built 2026-05-28
90-day totals
- Commits
- 186
- Grow
- 0.9
- Maintenance
- 18.5
- Fixes
- 0.5
- Total ETV
- 19.9
Where this dev ranks
Percentile against the global top-100 leaderboard (all-time totals).
- By commits
- Top 34 %
- By Growth share
- Top 98 %
30-day trajectory
Last 30 days vs. the 30 days before. Up arrows on Growth and ETV mean improvement; up arrow on Fixes share means more time on fixes (worse).
Daily performance
Daily ETV, stacked by Growth, Maintenance and Fixes.
Work-mix over time
Share of Growth / Maintenance / Fixes over a rolling 7-day window. Reads as 'where is effort flowing right now'.
Bug flow over time
Monthly bug flow attributed to this developer. The left bar (red) is bug impact this dev authored that was addressed in the given month — combining bugs others fixed for them and bugs they fixed themselves. The right bar is fixes they personally shipped that month, split between self-fixes (overlap with the red bar) and fixes done for someone else. X-axis is fix-time, not introduction-time — the Navigara API attributes bugs backward to the author at the moment the fix lands.
- Self-fix share
- 7%
- Bugs you introduced
- 1.6
- Bugs you fixed
- 2.1
Repository spread
Where this developer's commits land. Concentrated work (top1 > 80%) vs polymath spread (top1 < 30%).
Most impactful commits
Top 20 by ETV in the 90-day window.
- 0.8ETVReplace usages of deprecated AST method t_type_ref::get_type in Hack concat generator Summary: Replace usages of deprecated method `t_type_ref::get_type`. In generators, `t_type_ref` will always be either `empty` or `resolved`, because the Thrift compiler does not invoke the generator for ASTs that don't pass semantic validation. For resolved typedefs, we can translate `get_type` into the following using `t_type_ref`'s `deref`, `operator*` and `operator->`: | Before | After | | --- | --- | | `t_type* = ref.get_type()` | `t_type* = &ref.deref()` | | `t_type& = *ref.get_type()` | `t_type& = *ref` | | `ref.get_type()->foo()` | `ref->foo()` | For truly nullable cases (where the type ref might be empty/unresolved, due to being optional - e.g. `t_function::interaction`), we can translate `ref.get_type()` to the equivalent `t_type* = ref.resolved() ? &ref.deref() : nullptr`. Reviewed By: dtolnay Differential Revision: D101100276 fbshipit-source-id: b3b251f5e8c33bfa8e58b8f2c48f889c5985d23dgithub.com-facebook-fbthrift · e6a0fade · 2026-04-16
- 0.5ETVReplace usages of deprecated AST method t_type_ref::get_type in concat generators Summary: Replace usages of deprecated method `t_type_ref::get_type`. In generators, `t_type_ref` will always be either `empty` or `resolved`, because the Thrift compiler does not invoke the generator for ASTs that don't pass semantic validation. For resolved typedefs, we can translate `get_type` into the following using `t_type_ref`'s `deref`, `operator*` and `operator->`: | Before | After | | --- | --- | | `t_type* = ref.get_type()` | `t_type* = &ref.deref()` | | `t_type& = *ref.get_type()` | `t_type& = *ref` | | `ref.get_type()->foo()` | `ref->foo()` | For truly nullable cases (where the type ref might be empty/unresolved, due to being optional - e.g. `t_function::interaction`), we can translate `ref.get_type()` to the equivalent `t_type* = ref.resolved() ? &ref.deref() : nullptr`. ___ overriding_review_checks_triggers_an_audit_and_retroactive_review Oncall Short Name: thrift_qna Differential Revision: D101096216 fbshipit-source-id: 20099af4808cd739805e1e691efa189d1bcf4e67github.com-facebook-fbthrift · b8f51345 · 2026-04-16
- 0.5ETVReplace usages of deprecated AST method t_type_ref::get_type in Java deprecated concat generator Summary: Replace usages of deprecated method `t_type_ref::get_type`. In generators, `t_type_ref` will always be either `empty` or `resolved`, because the Thrift compiler does not invoke the generator for ASTs that don't pass semantic validation. For resolved typedefs, we can translate `get_type` into the following using `t_type_ref`'s `deref`, `operator*` and `operator->`: | Before | After | | --- | --- | | `t_type* = ref.get_type()` | `t_type* = &ref.deref()` | | `t_type& = *ref.get_type()` | `t_type& = *ref` | | `ref.get_type()->foo()` | `ref->foo()` | For truly nullable cases (where the type ref might be empty/unresolved, due to being optional - e.g. `t_function::interaction`), we can translate `ref.get_type()` to the equivalent `t_type* = ref.resolved() ? &ref.deref() : nullptr`. Reviewed By: dtolnay Differential Revision: D101096372 fbshipit-source-id: a567d2f6b087f2baa35a3fead0825dc838b52c5agithub.com-facebook-fbthrift · 397792ad · 2026-04-16
- 0.5ETVReplace usages of deprecated AST method t_type_ref::get_type in Whisker generators Summary: Replace usages of deprecated method `t_type_ref::get_type`. In generators, `t_type_ref` will always be either `empty` or `resolved`, because the Thrift compiler does not invoke the generator for ASTs that don't pass semantic validation. For resolved typedefs, we can translate `get_type` into the following using `t_type_ref`'s `deref`, `operator*` and `operator->`: | Before | After | | --- | --- | | `t_type* = ref.get_type()` | `t_type* = &ref.deref()` | | `t_type& = *ref.get_type()` | `t_type& = *ref` | | `ref.get_type()->foo()` | `ref->foo()` | For truly nullable cases (where the type ref might be empty/unresolved, due to being optional - e.g. `t_function::interaction`), we can translate `ref.get_type()` to the equivalent `t_type* = ref.resolved() ? &ref.deref() : nullptr`. Reviewed By: dtolnay Differential Revision: D101100275 fbshipit-source-id: a532d51d17a8568343708c6ee0823570cda66057github.com-facebook-fbthrift · c2b0b567 · 2026-04-16
- 0.5ETVMigrate py3 cython_cpp[_basic]_type templates to partials Reviewed By: vitaut Differential Revision: D94739059 fbshipit-source-id: b4f3cad1f7975c0a1a336e3c026a6605cf6f3b2dgithub.com-facebook-fbthrift · 9b0b33c0 · 2026-03-02
- 0.4ETVMigrate py3 program include handling to Whisker Summary: - Move `program:includeNamespaces` state generation into generator context - Move property accessor into Whisker prototype - Convert loops in templates and simplify conditions Reviewed By: praihan Differential Revision: D94962003 fbshipit-source-id: cefa6d914eae99a441545b2d44943cce82417295github.com-facebook-fbthrift · 30f26cc6 · 2026-03-03
- 0.4ETVMove Rust generator options processing to `process_options`, fix validation Summary: The Rust generator has validations to disallow the combination of adapter + serde on the same type. However, those validations were not currently enforced correctly - the Rust generator initialized its options in `generate_program`. This means the options were *not* initialized when `validate_program` runs. This change fixes the validation by initializing the options *before* the `fill_validator_visitors` validation runs. A new generator option (`deprecated_loose_adapter_serde`) is added to opt in to the legacy behavior for files that need to defer marking adapters as serde-compatible. NOTE: The `rust_serde_enabled` check is changed from `field` to the containing struct because the `rust.Serde` annotation is not allowed on fields. https://www.internalfb.com/code/fbsource/[6ce3eb479fbc26]/fbcode/thrift/annotation/rust.thrift?lines=272-279 Reviewed By: dtolnay Differential Revision: D98062650 fbshipit-source-id: e8e0b9ccbfca6212a4173509dc8219385c7ae80bgithub.com-facebook-fbthrift · 945f32a2 · 2026-03-25
- 0.3ETVReplace usages of and remove deprecated AST method t_type_ref::get_type Summary: Replace remaining usages of deprecated method `t_type_ref::get_type` and remove the method. In AST accessors, the type ref may yet be unresolved, so we need to explicitly validate. In generators, `t_type_ref` will always be either `empty` or `resolved`, because the Thrift compiler does not invoke the generator for ASTs that don't pass semantic validation. For resolved typedefs, we can translate `get_type` into the following using `t_type_ref`'s `deref`, `operator*` and `operator->`: | Before | After | | --- | --- | | `t_type* = ref.get_type()` | `t_type* = &ref.deref()` | | `t_type& = *ref.get_type()` | `t_type& = *ref` | | `ref.get_type()->foo()` | `ref->foo()` | For truly nullable cases (where the type ref might be empty/unresolved, due to being optional - e.g. `t_function::interaction`), we can translate `ref.get_type()` to the equivalent `t_type* = ref.resolved() ? &ref.deref() : nullptr`. Reviewed By: dtolnay Differential Revision: D101100274 fbshipit-source-id: 2951ab4faf6cb06b7dab75df9d138c672f93b8ebgithub.com-facebook-fbthrift · 075dc1f3 · 2026-04-20
- 0.3ETVExtract cpp2 service function type/param macros as Whisker partials Summary: Migrate 15 macro templates used across service .h/.cpp/.tcc and async client templates into Whisker partials. Reviewed By: iahs Differential Revision: D97123520 fbshipit-source-id: e52dfb26facef9a014b66ba0a564989e445093e2github.com-facebook-fbthrift · c3ae0ebd · 2026-03-19
- 0.3ETVMigrate additional py3 helper templates to Whisker partials Summary: Migrate helper templates with multiple usages to Whisker partials. Reviewed By: praihan Differential Revision: D95277207 fbshipit-source-id: 8c9a7b73c9f406fe2803960bbdd4df92a541ffd8github.com-facebook-fbthrift · 33bc2217 · 2026-03-05
- 0.3ETVReplace Rust type and ttype macros with Whisker partials Summary: Replace `type` and `ttype` macro usages with partials. Remove context switches like `{{#function:return_type}}{{> lib/type}}{{/function:return_type}}` where possible, by directly passing the equivalent Whisker type handle into the partial argument - `{{#partial types.type_name type=function:self.return_type}}`. Remove `args_by_name` (single usage) from function prototype - `function.params` returns a `t_paramlist` prototype which derives from `t_structured`, so we can leverage `fields_by_name` from the structured prototype. Simplified some conditions for first response types. The previous ones were of the form: ``` if bidirectional_stream if sink_has_first_response { bidi, initial response } if !sink_has_first_response { bidi, no initial response } if !bidirectional_stream if stream if stream_has_first_response { stream, initial response } if !stream_has_first_response { stream, no initial response } if sink if sink_has_first_response { sink, initial response } if !sink_has_first_response { sink, no initial response } if !sink && !stream { unary rpc response } ``` The simplified conditions take the following form, taking advantage of the fact that all of those response conditions are mutually exclusive, consolidating into a single if/else if/else condition, with a short `if/else` for initial/no initial response sub-scenarios. ``` if bidirectional_stream if sink_has_first_response { bidi, initial response } else { bidi, no initial response } else if stream if stream_has_first_response { stream, initial response } else { stream, no initial response } else if sink if sink_has_first_response { sink, initial } else { sink, no initial response } else { unary rpc response } ``` Reviewed By: dtolnay Differential Revision: D98242387 fbshipit-source-id: 46f234f6969087f1b8cf06d233e315bd4bf1298egithub.com-facebook-fbthrift · c8bfe389 · 2026-03-26
- 0.3ETVExtract progam and service split state to generator context Summary: Extract program and service splitting state from `cpp_mstch_program` / `cpp_mstch_service` into `cpp2_generator_context`. This makes the split state available to both mstch properties and Whisker prototypes, for implementing equivalent Whisker properties. Reviewed By: praihan Differential Revision: D96176602 fbshipit-source-id: 7bf1a0bd46095c7b1f224341aba80ec197cc2508github.com-facebook-fbthrift · be458a5c · 2026-03-12
- 0.3ETVMigrate service function properties to Whisker prototypes Summary: Remove the `rust_mstch_function` class and `rust_mstch_function_factory` by migrating their properties to Whisker prototypes. `service:rustFunctions` is replaced by the base `service:functions` mstch property. `function:index` is replaced by `array.enumerate` over `service:self.functions`. The `uniqueExceptions` family of properties are moved to Whisker prototypes on `t_function`, `t_stream`, and `t_sink`. The `rust_all_exceptions` method is converted from mstch to Whisker objects. Templates are updated to use the new property names and access patterns, with `field:type` (without `self.`) used inside Whisker-context loops. Reviewed By: slawlor Differential Revision: D98496567 fbshipit-source-id: 77bf0ed83f914f8c94f33d4c9a2ec15694e25a88github.com-facebook-fbthrift · 7c10609c · 2026-03-27
- 0.3ETVExtract cpp2 shared RPC helper macros as Whisker partials Reviewed By: iahs Differential Revision: D97182639 fbshipit-source-id: 1f82380dc9239432b5318c0f9c3ec236f210d732github.com-facebook-fbthrift · ed3cc6e5 · 2026-03-19
- 0.2ETVUpdate AST t_interaction to inherit directly from t_interface Summary: Update `t_interaction` to inherit directly from `t_interface`, rather than `t_service`. Reviewed By: iahs, praihan Differential Revision: D101081648 fbshipit-source-id: a9a779c6ac4c12449dc5689bb4fdb2d4e5d6f354github.com-facebook-fbthrift · ec190c9e · 2026-04-17
- 0.2ETVMigrate py3 cpython_python_type template to partial Summary: Migrate low-level helper template behind mstch-to-Whisker boundary in preparation for converting root level templates to Whisker-only rendering. Reviewed By: praihan Differential Revision: D94718545 fbshipit-source-id: 594605db9f24a3f118261c37e5939d0a7e8cd1c9github.com-facebook-fbthrift · b9244ae8 · 2026-02-28
- 0.2ETVMigrate cpp2 generator base class to t_whisker_generator Summary: Switch the cpp2 generator base class from `t_mstch_generator` to `t_whisker_generator` now that all templates are migrated to Whisker rendering. Reviewed By: iahs Differential Revision: D97377695 fbshipit-source-id: b9264dbe28ca37fb34b67619cdd9a8e7d3d6d14agithub.com-facebook-fbthrift · ae141fa0 · 2026-03-20
- 0.2ETVMove mstch_rust_value depth propagation into template partial argument Summary: - Convert `value` and `fieldvalue` templates to partials that take *mstch* objects and a `depth` argument - Move depth propagation into the depth argument of the new partials - Remove stateful depth propagation from the generator class There's likely some room for simplification and improvement of the partials, but this unblocks removing the depth state from the C++ layer. The templates can be cleaned up when changing them from taking mstch object args to Whisker native handles, as this changeset is already quite large. Reviewed By: vitaut Differential Revision: D98369757 fbshipit-source-id: 6dc98c5db955bd1ab9b1e10fb35d82b78603f360github.com-facebook-fbthrift · 13883967 · 2026-03-27
- 0.2ETVEnforce nullptr program on t_paramlist Summary: As with `t_throws`, a paramlist is an ephemeral compiler-internal structured node which is *not* owned by a program or named. Reviewed By: iahs Differential Revision: D101875117 fbshipit-source-id: be9e7c54911dfe1439df796fb6779d5947ca02f6github.com-facebook-fbthrift · b4500cda · 2026-04-23
- 0.2ETVConvert module_types_h macro dependencies to Whisker (1/2) Reviewed By: praihan Differential Revision: D96998983 fbshipit-source-id: c1b8d328af08a368962fbc42915f643c4b1044bbgithub.com-facebook-fbthrift · 20efc718 · 2026-03-18