From ee78707177afc04b53638c94dad6e8562420af91 Mon Sep 17 00:00:00 2001 From: daiwei Date: Fri, 3 Sep 2021 23:54:47 +0800 Subject: [PATCH 1/3] feat(sfc): support using extends interface with defineProps() --- .../__snapshots__/compileScript.spec.ts.snap | 25 ++++++ .../__tests__/compileScript.spec.ts | 22 ++++++ packages/compiler-sfc/src/compileScript.ts | 79 +++++++++++++++---- 3 files changed, 109 insertions(+), 17 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index 54591d402bd..373b8e1766b 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -924,6 +924,31 @@ export default /*#__PURE__*/_defineComponent({ +return { } +} + +})" +`; + +exports[`SFC compile + `) + assertCode(content) + expect(content).toMatch(`x: { type: Number, required: false }`) + expect(content).toMatch(`y: { type: Number, required: false }`) + expect(content).toMatch(`z: { type: Number, required: true }`) + expect(bindings).toStrictEqual({ + x: BindingTypes.PROPS, + y: BindingTypes.PROPS, + z: BindingTypes.PROPS + }) + }) + test('defineProps w/ exported interface', () => { const { content, bindings } = compile(` `) assertCode(content) - expect(content).toMatch(`x: { type: Number, required: false }`) - expect(content).toMatch(`y: { type: Number, required: false }`) expect(content).toMatch(`z: { type: Number, required: true }`) + expect(content).toMatch(`y: { type: String, required: true }`) + expect(content).toMatch(`x: { type: Number, required: false }`) expect(bindings).toStrictEqual({ x: BindingTypes.PROPS, y: BindingTypes.PROPS, diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index b15a08e3c35..e57c37bfa74 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -458,7 +458,7 @@ export function compileScript( extend.expression.name ) if (qualified) { - cache.unshift(qualified) + cache.push(qualified) resolveExtendsType(node, qualifier, cache) return cache } @@ -487,6 +487,28 @@ export function compileScript( } } + // filter all extends types to keep the override declaration + function filterExtendsType(extendsTypes: Node[], bodies: TSTypeElement[]) { + extendsTypes.forEach(extend => { + const body = (extend as TSInterfaceBody).body + body.forEach(newBody => { + if ( + newBody.type === 'TSPropertySignature' && + newBody.key.type === 'Identifier' + ) { + const name = newBody.key.name + const hasOverride = bodies.some( + seenBody => + seenBody.type === 'TSPropertySignature' && + seenBody.key.type === 'Identifier' && + seenBody.key.name === name + ) + if (!hasOverride) bodies.push(newBody) + } + }) + }) + } + function resolveQualifiedType( node: Node, qualifier: (node: Node) => boolean @@ -511,11 +533,8 @@ export function compileScript( if (qualified) { const extendsTypes = resolveExtendsType(node, qualifier) if (extendsTypes.length) { - const bodies: TSTypeElement[] = [] - extendsTypes.forEach(extend => { - bodies.push(...(extend as TSInterfaceBody).body) - }) - bodies.push(...qualified.body) + const bodies: TSTypeElement[] = [...qualified.body] + filterExtendsType(extendsTypes, bodies) qualified.body = bodies } return qualified From c8af08d7ede410132a2eb699f688ae58b3269dd0 Mon Sep 17 00:00:00 2001 From: daiwei Date: Mon, 6 Sep 2021 09:01:39 +0800 Subject: [PATCH 3/3] chore: improve code --- .../__snapshots__/compileScript.spec.ts.snap | 15 ++++++++------- .../compiler-sfc/__tests__/compileScript.spec.ts | 16 +++++++++------- packages/compiler-sfc/src/compileScript.ts | 13 +++++++++---- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap index 009a16a8851..befdf2f2797 100644 --- a/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap +++ b/packages/compiler-sfc/__tests__/__snapshots__/compileScript.spec.ts.snap @@ -913,12 +913,13 @@ return { } exports[`SFC compile `) assertCode(content) diff --git a/packages/compiler-sfc/src/compileScript.ts b/packages/compiler-sfc/src/compileScript.ts index e57c37bfa74..fe7f2222d89 100644 --- a/packages/compiler-sfc/src/compileScript.ts +++ b/packages/compiler-sfc/src/compileScript.ts @@ -440,6 +440,12 @@ export function compileScript( return true } + function getAstBody(): Statement[] { + return scriptAst + ? [...scriptSetupAst.body, ...scriptAst.body] + : scriptSetupAst.body + } + function resolveExtendsType( node: Node, qualifier: (node: Node) => boolean, @@ -451,7 +457,8 @@ export function compileScript( extend.type === 'TSExpressionWithTypeArguments' && extend.expression.type === 'Identifier' ) { - for (const node of scriptSetupAst.body) { + const body = getAstBody() + for (const node of body) { const qualified = isQualifiedType( node, qualifier, @@ -521,9 +528,7 @@ export function compileScript( node.typeName.type === 'Identifier' ) { const refName = node.typeName.name - const body = scriptAst - ? [...scriptSetupAst.body, ...scriptAst.body] - : scriptSetupAst.body + const body = getAstBody() for (const node of body) { let qualified = isQualifiedType( node,