From a10585e4aee65181602fa44de08e47b7826a7880 Mon Sep 17 00:00:00 2001 From: jimcody1995 Date: Mon, 6 Jul 2026 11:11:59 +0200 Subject: [PATCH] fix(signals): classify Rust prost/tonic underscore protobuf stubs as generated Recognize *_pb.rs and *_grpc_pb.rs alongside the existing .pb.rs matcher so replay/snapshot diff classification treats prost/tonic underscore output as machine-generated. Fixes #3010 Co-authored-by: Cursor --- src/signals/path-matchers.ts | 6 +++++- test/unit/path-matchers.test.ts | 11 +++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/signals/path-matchers.ts b/src/signals/path-matchers.ts index 5d306063a9..967377a71f 100644 --- a/src/signals/path-matchers.ts +++ b/src/signals/path-matchers.ts @@ -78,7 +78,8 @@ function isGeneratedFileFrom(parts: NormalizedPath): boolean { // `.pb.cc` / `.pb.h`, the Swift plugin emits `.pb.swift`, the Dart plugin emits `.pb.dart`, // the Kotlin plugin emits `.pb.kt`, the Java plugin emits `.pb.java`, the C# plugin emits `.pb.cs`, the Rust plugin emits `.pb.rs`, // the Elixir plugin emits `.pb.ex`, the Erlang gpb plugin emits `.pb.erl` / `.pb.hrl`, the Crystal - // plugin emits `.pb.cr`, the Haskell plugin emits `.pb.hs`, the Scala plugin emits `.pb.scala`, and the Objective-C plugin emits + // plugin emits `.pb.cr`, the Haskell plugin emits `.pb.hs`, the Scala plugin emits `.pb.scala`, the Rust + // plugin emits `.pb.rs` (and prost/tonic also emit underscore `*_pb.rs` / `*_grpc_pb.rs` siblings), and the Objective-C plugin emits // `.pbobjc.{h,m}` plus gRPC `.pbrpc.{h,m}` service stubs. Swift gRPC emits sibling `.grpc.swift` // service stubs; grpc-kotlin emits sibling `*GrpcKt.kt` coroutine service stubs; grpc-java emits // sibling `*Grpc.java` service stubs; grpc-dotnet emits sibling `*Grpc.cs` service stubs; the Dart @@ -108,6 +109,9 @@ function isGeneratedFileFrom(parts: NormalizedPath): boolean { /_pb\.lua$/.test(norm) || // Perl protobuf: message stubs are `*_pb.pm`. /_pb\.pm$/.test(norm) || + // Rust prost/tonic underscore stubs: `*_pb.rs` message output; tonic gRPC emits sibling `*_grpc_pb.rs`. + /_pb\.rs$/.test(norm) || + /_grpc_pb\.rs$/.test(norm) || // JavaScript/TypeScript grpc-node protobuf: message stubs are `*_pb.{js,ts,d.ts}`; gRPC emits // sibling `*_grpc_pb.{js,ts,d.ts}` service stubs (underscore form, not `.pb.js`). /_pb\.(js|ts)$/.test(norm) || diff --git a/test/unit/path-matchers.test.ts b/test/unit/path-matchers.test.ts index 973ff17e18..de34039e65 100644 --- a/test/unit/path-matchers.test.ts +++ b/test/unit/path-matchers.test.ts @@ -169,6 +169,15 @@ describe("isGeneratedFile", () => { expect(classifyChangedFile("proto/messages.pb.scala")).toBe("generated"); }); + it("matches Rust prost/tonic underscore protobuf stubs alongside the dot-pb spellings", () => { + expect(isGeneratedFile("gen/service_pb.rs")).toBe(true); + expect(isGeneratedFile("gen/service_grpc_pb.rs")).toBe(true); + expect(isGeneratedFile("src/lib.rs")).toBe(false); + expect(isGeneratedFile("src/main.rs")).toBe(false); + expect(classifyChangedFile("gen/service_pb.rs")).toBe("generated"); + expect(classifyChangedFile("gen/service_grpc_pb.rs")).toBe("generated"); + }); + it("matches Kotlin gRPC coroutine stubs alongside the other protoc plugins", () => { expect(isGeneratedFile("gen/GreeterGrpcKt.kt")).toBe(true); expect(isGeneratedFile("src/Greeter.kt")).toBe(false); @@ -543,6 +552,8 @@ describe("classifyChangedFile", () => { ["gen/service_pb.lua", "generated"], ["gen/service_pb.pm", "generated"], ["proto/messages.pb.scala", "generated"], + ["gen/service_pb.rs", "generated"], + ["gen/service_grpc_pb.rs", "generated"], ["gen/GreeterGrpcKt.kt", "generated"], ["gen/GreeterGrpc.java", "generated"], ["proto/messages.pb.java", "generated"],