From d8c26b1580292423a63c2a1c42cc08a620c0b817 Mon Sep 17 00:00:00 2001 From: Timothee Guerin Date: Mon, 6 May 2024 13:48:00 -0700 Subject: [PATCH] Templated interface extending another templated interface shouldn't run decorator on their operations (#3287) fix #3286 --- ...nish-cloned-unfinished-2024-4-6-20-0-24.md | 8 ++++++++ packages/compiler/src/core/checker.ts | 4 +++- .../compiler/test/checker/interface.test.ts | 19 +++++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .chronus/changes/fix-no-finish-cloned-unfinished-2024-4-6-20-0-24.md diff --git a/.chronus/changes/fix-no-finish-cloned-unfinished-2024-4-6-20-0-24.md b/.chronus/changes/fix-no-finish-cloned-unfinished-2024-4-6-20-0-24.md new file mode 100644 index 0000000000..20038ff610 --- /dev/null +++ b/.chronus/changes/fix-no-finish-cloned-unfinished-2024-4-6-20-0-24.md @@ -0,0 +1,8 @@ +--- +# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking +changeKind: fix +packages: + - "@typespec/compiler" +--- + +Templated interface extending another templated interface shouldn't run decorator on their operations diff --git a/packages/compiler/src/core/checker.ts b/packages/compiler/src/core/checker.ts index 0ac906ca26..a693f612f8 100644 --- a/packages/compiler/src/core/checker.ts +++ b/packages/compiler/src/core/checker.ts @@ -4724,7 +4724,9 @@ export function createChecker(program: Program): Checker { clone.decorators.push(dec); } } - clone = finishType(clone); + if (type.isFinished) { + clone = finishType(clone); + } compilerAssert(clone.kind === type.kind, "cloneType must not change type kind"); return clone; } diff --git a/packages/compiler/test/checker/interface.test.ts b/packages/compiler/test/checker/interface.test.ts index 5b3b4b5bd9..47606886b1 100644 --- a/packages/compiler/test/checker/interface.test.ts +++ b/packages/compiler/test/checker/interface.test.ts @@ -429,6 +429,25 @@ describe("compiler: interfaces", () => { expect($track).not.toHaveBeenCalled(); }); + it("templated interface extending another templated interface doesn't run decorator on extended interface operations", async () => { + const $track = vi.fn(); + testHost.addJsFile("dec.js", { $track }); + testHost.addTypeSpecFile( + "main.tsp", + ` + import "./dec.js"; + + interface Base { + @track bar(): T; + } + + interface Foo extends Base {} + ` + ); + await testHost.compile("./"); + expect($track).not.toHaveBeenCalled(); + }); + it("emit warning if shadowing parent templated type", async () => { const diagnostics = await runner.diagnose(` interface Base {