From 9b846c65985ac1523b5dc92479b51502ea62fcc0 Mon Sep 17 00:00:00 2001 From: Ben Tefay Date: Thu, 5 May 2022 22:07:12 +1000 Subject: [PATCH] Fix Go To Definition for inferred merged object properties --- .../languageServerFeatures.source.ts | 6 ++- .../__tests__/languageServerFeatures.test.ts | 52 +++++++++++++++++-- deno/lib/types.ts | 4 +- .../languageServerFeatures.source.ts | 6 ++- src/__tests__/languageServerFeatures.test.ts | 52 +++++++++++++++++-- src/types.ts | 4 +- 6 files changed, 108 insertions(+), 16 deletions(-) diff --git a/deno/lib/__tests__/languageServerFeatures.source.ts b/deno/lib/__tests__/languageServerFeatures.source.ts index 0153542cf..55670263d 100644 --- a/deno/lib/__tests__/languageServerFeatures.source.ts +++ b/deno/lib/__tests__/languageServerFeatures.source.ts @@ -12,7 +12,7 @@ export const instanceOfTest: Test = { export const TestMerge = z .object({ - f5: z.literal("literal").optional(), + f2: z.string().optional(), }) .merge(Test); @@ -20,11 +20,12 @@ export type TestMerge = z.infer; export const instanceOfTestMerge: TestMerge = { f1: 1, + f2: "string", }; export const TestUnion = z.union([ z.object({ - f2: z.literal("literal").optional(), + f2: z.string().optional(), }), Test, ]); @@ -33,6 +34,7 @@ export type TestUnion = z.infer; export const instanceOfTestUnion: TestUnion = { f1: 1, + f2: "string", }; export const TestPartial = Test.partial(); diff --git a/deno/lib/__tests__/languageServerFeatures.test.ts b/deno/lib/__tests__/languageServerFeatures.test.ts index 658f7499d..f697f1668 100644 --- a/deno/lib/__tests__/languageServerFeatures.test.ts +++ b/deno/lib/__tests__/languageServerFeatures.test.ts @@ -16,7 +16,7 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac }); const sourceFile = project.addSourceFileAtPath(filePath); - test("works for objects", () => { + test("works for simple object properties", () => { // Find usage of Test.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow("instanceOfTest"); @@ -36,7 +36,7 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); - test("works for merged objects", () => { + test("works for first merged object properties", () => { // Find usage of TestMerge.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( "instanceOfTestMerge" @@ -57,7 +57,30 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); - test("works for unioned objects", () => { + test("works for second merged object properties", () => { + // Find usage of TestMerge.f2 property + const instanceVariable = sourceFile.getVariableDeclarationOrThrow( + "instanceOfTestMerge" + ); + const propertyBeingAssigned = getPropertyBeingAssigned( + instanceVariable, + "f2" + ); + + // Find definition of TestMerge.f2 property + const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; + const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( + SyntaxKind.VariableDeclaration + ); + + // Assert that find definition returned the Zod definition of TestMerge + expect(definitionOfProperty?.getText()).toEqual( + "f2: z.string().optional()" + ); + expect(parentOfProperty?.getName()).toEqual("TestMerge"); + }); + + test("works for first unioned object properties", () => { // Find usage of TestUnion.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( "instanceOfTestUnion" @@ -78,6 +101,29 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); + test("works for second unioned object properties", () => { + // Find usage of TestUnion.f2 property + const instanceVariable = sourceFile.getVariableDeclarationOrThrow( + "instanceOfTestUnion" + ); + const propertyBeingAssigned = getPropertyBeingAssigned( + instanceVariable, + "f2" + ); + + // Find definition of TestUnion.f2 property + const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; + const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( + SyntaxKind.VariableDeclaration + ); + + // Assert that find definition returned the Zod definition of TestUnion + expect(definitionOfProperty?.getText()).toEqual( + "f2: z.string().optional()" + ); + expect(parentOfProperty?.getName()).toEqual("TestUnion"); + }); + test("works for partial objects", () => { // Find usage of TestPartial.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 6de7d3e73..574da5f7b 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -1393,9 +1393,7 @@ export namespace objectUtil { }; } -export type extendShape = { - [k in Exclude]: A[k]; -} & { [k in keyof B]: B[k] }; +export type extendShape = Omit & B; const AugmentFactory = (def: Def) => diff --git a/src/__tests__/languageServerFeatures.source.ts b/src/__tests__/languageServerFeatures.source.ts index 6de80ec49..ea600cdec 100644 --- a/src/__tests__/languageServerFeatures.source.ts +++ b/src/__tests__/languageServerFeatures.source.ts @@ -12,7 +12,7 @@ export const instanceOfTest: Test = { export const TestMerge = z .object({ - f5: z.literal("literal").optional(), + f2: z.string().optional(), }) .merge(Test); @@ -20,11 +20,12 @@ export type TestMerge = z.infer; export const instanceOfTestMerge: TestMerge = { f1: 1, + f2: "string", }; export const TestUnion = z.union([ z.object({ - f2: z.literal("literal").optional(), + f2: z.string().optional(), }), Test, ]); @@ -33,6 +34,7 @@ export type TestUnion = z.infer; export const instanceOfTestUnion: TestUnion = { f1: 1, + f2: "string", }; export const TestPartial = Test.partial(); diff --git a/src/__tests__/languageServerFeatures.test.ts b/src/__tests__/languageServerFeatures.test.ts index 34249bb5e..096cbc946 100644 --- a/src/__tests__/languageServerFeatures.test.ts +++ b/src/__tests__/languageServerFeatures.test.ts @@ -15,7 +15,7 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac }); const sourceFile = project.addSourceFileAtPath(filePath); - test("works for objects", () => { + test("works for simple object properties", () => { // Find usage of Test.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow("instanceOfTest"); @@ -35,7 +35,7 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); - test("works for merged objects", () => { + test("works for first merged object properties", () => { // Find usage of TestMerge.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( "instanceOfTestMerge" @@ -56,7 +56,30 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); - test("works for unioned objects", () => { + test("works for second merged object properties", () => { + // Find usage of TestMerge.f2 property + const instanceVariable = sourceFile.getVariableDeclarationOrThrow( + "instanceOfTestMerge" + ); + const propertyBeingAssigned = getPropertyBeingAssigned( + instanceVariable, + "f2" + ); + + // Find definition of TestMerge.f2 property + const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; + const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( + SyntaxKind.VariableDeclaration + ); + + // Assert that find definition returned the Zod definition of TestMerge + expect(definitionOfProperty?.getText()).toEqual( + "f2: z.string().optional()" + ); + expect(parentOfProperty?.getName()).toEqual("TestMerge"); + }); + + test("works for first unioned object properties", () => { // Find usage of TestUnion.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( "instanceOfTestUnion" @@ -77,6 +100,29 @@ describe("Executing Go To Definition (and therefore Find Usages and Rename Refac expect(parentOfProperty?.getName()).toEqual("Test"); }); + test("works for second unioned object properties", () => { + // Find usage of TestUnion.f2 property + const instanceVariable = sourceFile.getVariableDeclarationOrThrow( + "instanceOfTestUnion" + ); + const propertyBeingAssigned = getPropertyBeingAssigned( + instanceVariable, + "f2" + ); + + // Find definition of TestUnion.f2 property + const definitionOfProperty = propertyBeingAssigned?.getDefinitionNodes()[0]; + const parentOfProperty = definitionOfProperty?.getFirstAncestorByKind( + SyntaxKind.VariableDeclaration + ); + + // Assert that find definition returned the Zod definition of TestUnion + expect(definitionOfProperty?.getText()).toEqual( + "f2: z.string().optional()" + ); + expect(parentOfProperty?.getName()).toEqual("TestUnion"); + }); + test("works for partial objects", () => { // Find usage of TestPartial.f1 property const instanceVariable = sourceFile.getVariableDeclarationOrThrow( diff --git a/src/types.ts b/src/types.ts index 05eee3536..90e366b12 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1393,9 +1393,7 @@ export namespace objectUtil { }; } -export type extendShape = { - [k in Exclude]: A[k]; -} & { [k in keyof B]: B[k] }; +export type extendShape = Omit & B; const AugmentFactory = (def: Def) =>