diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4875b43d4e867..d3f752b931ac0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -47336,7 +47336,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const errorMessage = overriddenInstanceProperty ? Diagnostics._0_is_defined_as_an_accessor_in_class_1_but_is_overridden_here_in_2_as_an_instance_property : Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor; - error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(baseType), typeToString(type)); + error(getNameOfDeclaration(derived.valueDeclaration) || derived.valueDeclaration, errorMessage, symbolToString(base), typeToString(getDeclaredTypeOfSymbol(base.parent!)), typeToString(type)); } else if (useDefineForClassFields) { const uninitialized = derived.declarations?.find(d => d.kind === SyntaxKind.PropertyDeclaration && !(d as PropertyDeclaration).initializer); diff --git a/src/services/codefixes/fixAddMissingMember.ts b/src/services/codefixes/fixAddMissingMember.ts index 471cbab82c6c9..17ff1280f40c0 100644 --- a/src/services/codefixes/fixAddMissingMember.ts +++ b/src/services/codefixes/fixAddMissingMember.ts @@ -7,7 +7,6 @@ import { createSignatureDeclarationFromSignature, createStubbedBody, eachDiagnostic, - getAllSupers, ImportAdder, registerCodeFix, } from "../_namespaces/ts.codefix.js"; @@ -40,6 +39,7 @@ import { firstOrUndefinedIterator, FunctionExpression, getCheckFlags, + getClassExtendsHeritageElement, getClassLikeDeclarationOfSymbol, getEmitScriptTarget, getEscapedTextOfJsxAttributeName, @@ -797,3 +797,18 @@ function findScope(node: Node) { } return getSourceFileOfNode(node); } + +function getAllSupers(decl: ClassLikeDeclaration | InterfaceDeclaration | undefined, checker: TypeChecker): readonly ClassLikeDeclaration[] { + const res: ClassLikeDeclaration[] = []; + while (decl) { + const superElement = getClassExtendsHeritageElement(decl); + const superSymbol = superElement && checker.getSymbolAtLocation(superElement.expression); + if (!superSymbol) break; + const symbol = superSymbol.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(superSymbol) : superSymbol; + const superDecl = symbol.declarations && find(symbol.declarations, isClassLike); + if (!superDecl) break; + res.push(superDecl); + decl = superDecl; + } + return res; +} diff --git a/src/services/codefixes/fixPropertyOverrideAccessor.ts b/src/services/codefixes/fixPropertyOverrideAccessor.ts index c1b446bcf7d34..2c831d9efb400 100644 --- a/src/services/codefixes/fixPropertyOverrideAccessor.ts +++ b/src/services/codefixes/fixPropertyOverrideAccessor.ts @@ -2,7 +2,6 @@ import { codeFixAll, createCodeFixAction, generateAccessorFromProperty, - getAllSupers, registerCodeFix, } from "../_namespaces/ts.codefix.js"; import { @@ -10,12 +9,15 @@ import { CodeFixContext, Debug, Diagnostics, + getEffectiveBaseTypeNode, getSourceFileOfNode, getTextOfPropertyName, getTokenAtPosition, isAccessor, + isClassExpression, isClassLike, - singleOrUndefined, + isComputedPropertyName, + skipParentheses, SourceFile, unescapeLeadingUnderscores, } from "../_namespaces/ts.js"; @@ -56,15 +58,20 @@ function doChange(file: SourceFile, start: number, length: number, code: number, else if (code === Diagnostics._0_is_defined_as_a_property_in_class_1_but_is_overridden_here_in_2_as_an_accessor.code) { const checker = context.program.getTypeChecker(); const node = getTokenAtPosition(file, start).parent; + if (isComputedPropertyName(node)) { + return; + } Debug.assert(isAccessor(node), "error span of fixPropertyOverrideAccessor should only be on an accessor"); const containingClass = node.parent; Debug.assert(isClassLike(containingClass), "erroneous accessors should only be inside classes"); - const base = singleOrUndefined(getAllSupers(containingClass, checker)); - if (!base) return []; - - const name = unescapeLeadingUnderscores(getTextOfPropertyName(node.name)); - const baseProp = checker.getPropertyOfType(checker.getTypeAtLocation(base), name); - if (!baseProp || !baseProp.valueDeclaration) return []; + const baseTypeNode = getEffectiveBaseTypeNode(containingClass); + if (!baseTypeNode) return; + const expression = skipParentheses(baseTypeNode.expression); + const base = isClassExpression(expression) ? expression.symbol : checker.getSymbolAtLocation(expression); + if (!base) return; + const baseType = checker.getDeclaredTypeOfSymbol(base); + const baseProp = checker.getPropertyOfType(baseType, unescapeLeadingUnderscores(getTextOfPropertyName(node.name))); + if (!baseProp || !baseProp.valueDeclaration) return; startPosition = baseProp.valueDeclaration.pos; endPosition = baseProp.valueDeclaration.end; diff --git a/src/services/codefixes/generateAccessors.ts b/src/services/codefixes/generateAccessors.ts index 75837f080749f..76ffd62b2c9a4 100644 --- a/src/services/codefixes/generateAccessors.ts +++ b/src/services/codefixes/generateAccessors.ts @@ -9,9 +9,7 @@ import { Diagnostics, factory, FileTextChanges, - find, findAncestor, - getClassExtendsHeritageElement, getDecorators, getEffectiveModifierFlags, getFirstConstructorWithBody, @@ -22,7 +20,6 @@ import { hasEffectiveReadonlyModifier, hasStaticModifier, Identifier, - InterfaceDeclaration, isClassLike, isElementAccessExpression, isFunctionLike, @@ -50,10 +47,8 @@ import { startsWithUnderscore, StringLiteral, suppressLeadingAndTrailingTrivia, - SymbolFlags, SyntaxKind, textChanges, - TypeChecker, TypeNode, } from "../_namespaces/ts.js"; @@ -321,22 +316,3 @@ function getDeclarationType(declaration: AcceptedDeclaration, program: Program): } return typeNode; } - -/** @internal */ -export function getAllSupers(decl: ClassOrInterface | undefined, checker: TypeChecker): readonly ClassOrInterface[] { - const res: ClassLikeDeclaration[] = []; - while (decl) { - const superElement = getClassExtendsHeritageElement(decl); - const superSymbol = superElement && checker.getSymbolAtLocation(superElement.expression); - if (!superSymbol) break; - const symbol = superSymbol.flags & SymbolFlags.Alias ? checker.getAliasedSymbol(superSymbol) : superSymbol; - const superDecl = symbol.declarations && find(symbol.declarations, isClassLike); - if (!superDecl) break; - res.push(superDecl); - decl = superDecl; - } - return res; -} - -/** @internal */ -export type ClassOrInterface = ClassLikeDeclaration | InterfaceDeclaration; diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index 48fdb95aa0cff..b8b131ca3b56f 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -51,6 +51,7 @@ import { isClassExpression, isClassLike, isClassStaticBlockDeclaration, + isComputedPropertyName, isConstructorDeclaration, isDeclarationFileName, isDefaultClause, @@ -64,6 +65,7 @@ import { isJSDocOverrideTag, isJsxOpeningLikeElement, isJumpStatementTarget, + isKnownSymbol, isModifier, isModuleSpecifierLike, isNamedDeclaration, @@ -328,14 +330,29 @@ function getDefinitionFromOverriddenMember(typeChecker: TypeChecker, node: Node) const expression = skipParentheses(baseTypeNode.expression); const base = isClassExpression(expression) ? expression.symbol : typeChecker.getSymbolAtLocation(expression); if (!base) return; + const baseType = hasStaticModifier(classElement) ? typeChecker.getTypeOfSymbol(base) : typeChecker.getDeclaredTypeOfSymbol(base); + let baseProp: Symbol | undefined; - const name = unescapeLeadingUnderscores(getTextOfPropertyName(classElement.name)); - const symbol = hasStaticModifier(classElement) - ? typeChecker.getPropertyOfType(typeChecker.getTypeOfSymbol(base), name) - : typeChecker.getPropertyOfType(typeChecker.getDeclaredTypeOfSymbol(base), name); - if (!symbol) return; + if (isComputedPropertyName(classElement.name)) { + const prop = typeChecker.getSymbolAtLocation(classElement.name); - return getDefinitionFromSymbol(typeChecker, symbol, node); + if (!prop) { + return; + } + + if (isKnownSymbol(prop)) { + baseProp = find(typeChecker.getPropertiesOfType(baseType), s => s.escapedName === prop.escapedName); + } + else { + baseProp = typeChecker.getPropertyOfType(baseType, unescapeLeadingUnderscores(prop.escapedName)); + } + } + else { + baseProp = typeChecker.getPropertyOfType(baseType, unescapeLeadingUnderscores(getTextOfPropertyName(classElement.name))); + } + if (!baseProp) return; + + return getDefinitionFromSymbol(typeChecker, baseProp, node); } /** @internal */ diff --git a/tests/baselines/reference/accessorsOverrideProperty10.errors.txt b/tests/baselines/reference/accessorsOverrideProperty10.errors.txt new file mode 100644 index 0000000000000..9ba82aa7b4f5f --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty10.errors.txt @@ -0,0 +1,16 @@ +accessorsOverrideProperty10.ts(6,7): error TS2611: 'x' is defined as a property in class 'A', but is overridden here in 'C' as an accessor. + + +==== accessorsOverrideProperty10.ts (1 errors) ==== + class A { + x = 1; + } + class B extends A {} + class C extends B { + get x() { + ~ +!!! error TS2611: 'x' is defined as a property in class 'A', but is overridden here in 'C' as an accessor. + return 2; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/accessorsOverrideProperty10.symbols b/tests/baselines/reference/accessorsOverrideProperty10.symbols new file mode 100644 index 0000000000000..f0b2c93f29d02 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty10.symbols @@ -0,0 +1,24 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty10.ts] //// + +=== accessorsOverrideProperty10.ts === +class A { +>A : Symbol(A, Decl(accessorsOverrideProperty10.ts, 0, 0)) + + x = 1; +>x : Symbol(A.x, Decl(accessorsOverrideProperty10.ts, 0, 9)) +} +class B extends A {} +>B : Symbol(B, Decl(accessorsOverrideProperty10.ts, 2, 1)) +>A : Symbol(A, Decl(accessorsOverrideProperty10.ts, 0, 0)) + +class C extends B { +>C : Symbol(C, Decl(accessorsOverrideProperty10.ts, 3, 20)) +>B : Symbol(B, Decl(accessorsOverrideProperty10.ts, 2, 1)) + + get x() { +>x : Symbol(C.x, Decl(accessorsOverrideProperty10.ts, 4, 19)) + + return 2; + } +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty10.types b/tests/baselines/reference/accessorsOverrideProperty10.types new file mode 100644 index 0000000000000..8615b3d534492 --- /dev/null +++ b/tests/baselines/reference/accessorsOverrideProperty10.types @@ -0,0 +1,35 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty10.ts] //// + +=== accessorsOverrideProperty10.ts === +class A { +>A : A +> : ^ + + x = 1; +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ +} +class B extends A {} +>B : B +> : ^ +>A : A +> : ^ + +class C extends B { +>C : C +> : ^ +>B : B +> : ^ + + get x() { +>x : number +> : ^^^^^^ + + return 2; +>2 : 2 +> : ^ + } +} + diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember17.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember17.baseline.jsonc new file mode 100644 index 0000000000000..4695ad301d280 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember17.baseline.jsonc @@ -0,0 +1,23 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember17.ts === +// const entityKind = Symbol.for("drizzle:entityKind"); +// +// abstract class MySqlColumn { +// <|static readonly [|[entityKind]|]: string = "MySqlColumn";|> +// } +// +// export class MySqlVarBinary extends MySqlColumn { +// static /*GOTO DEF*/override readonly [entityKind]: string = "MySqlVarBinary"; +// } + + // === Details === + [ + { + "kind": "property", + "name": "[entityKind]", + "containerName": "MySqlColumn", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember18.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember18.baseline.jsonc new file mode 100644 index 0000000000000..c43d1d6aac3a8 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember18.baseline.jsonc @@ -0,0 +1,23 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember18.ts === +// const entityKind = Symbol.for("drizzle:entityKind"); +// +// abstract class MySqlColumn { +// <|readonly [|[entityKind]|]: string = "MySqlColumn";|> +// } +// +// export class MySqlVarBinary extends MySqlColumn { +// /*GOTO DEF*/override readonly [entityKind]: string = "MySqlVarBinary"; +// } + + // === Details === + [ + { + "kind": "property", + "name": "[entityKind]", + "containerName": "MySqlColumn", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember19.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember19.baseline.jsonc new file mode 100644 index 0000000000000..cdcacbeb56245 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember19.baseline.jsonc @@ -0,0 +1,23 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember19.ts === +// const prop = "foo" as const; +// +// abstract class A { +// <|static readonly [|[prop]|] = "A";|> +// } +// +// export class B extends A { +// static /*GOTO DEF*/override readonly [prop] = "B"; +// } + + // === Details === + [ + { + "kind": "property", + "name": "[prop]", + "containerName": "A", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember20.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember20.baseline.jsonc new file mode 100644 index 0000000000000..7c16b895ffd07 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember20.baseline.jsonc @@ -0,0 +1,23 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember20.ts === +// const prop = "foo" as const; +// +// abstract class A { +// <|readonly [|[prop]|] = "A";|> +// } +// +// export class B extends A { +// /*GOTO DEF*/override readonly [prop] = "B"; +// } + + // === Details === + [ + { + "kind": "property", + "name": "[prop]", + "containerName": "A", + "isLocal": true, + "isAmbient": false, + "unverified": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember21.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember21.baseline.jsonc new file mode 100644 index 0000000000000..94eb0f3896e25 --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember21.baseline.jsonc @@ -0,0 +1,22 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember21.ts === +// const prop = "foo" as const; +// +// abstract class A {} +// +// export class B extends A { +// <|static /*GOTO DEF*/override readonly [|[prop]|] = "B";|> +// } + + // === Details === + [ + { + "kind": "property", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember22.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember22.baseline.jsonc new file mode 100644 index 0000000000000..a52d8e8b1945d --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember22.baseline.jsonc @@ -0,0 +1,22 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember22.ts === +// const prop = "foo" as const; +// +// abstract class A {} +// +// export class B extends A { +// /*GOTO DEF*/<|override readonly [|[prop]|] = "B";|> +// } + + // === Details === + [ + { + "kind": "property", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember23.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember23.baseline.jsonc new file mode 100644 index 0000000000000..7007ff335575f --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember23.baseline.jsonc @@ -0,0 +1,21 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember23.ts === +// --- (line: 4) skipped --- +// } +// +// export class B extends A { +// <|static /*GOTO DEF*/override [|[prop]|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember24.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember24.baseline.jsonc new file mode 100644 index 0000000000000..f6222b4352c2d --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember24.baseline.jsonc @@ -0,0 +1,21 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember24.ts === +// --- (line: 4) skipped --- +// } +// +// export class B extends A { +// /*GOTO DEF*/<|override [|[prop]|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember25.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember25.baseline.jsonc new file mode 100644 index 0000000000000..63658d0c3ccdc --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember25.baseline.jsonc @@ -0,0 +1,22 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember25.ts === +// const prop: symbol = Symbol(); +// +// abstract class A {} +// +// export class B extends A { +// <|static /*GOTO DEF*/override [|[prop]|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/goToDefinitionOverriddenMember26.baseline.jsonc b/tests/baselines/reference/goToDefinitionOverriddenMember26.baseline.jsonc new file mode 100644 index 0000000000000..2ced39b72e2fc --- /dev/null +++ b/tests/baselines/reference/goToDefinitionOverriddenMember26.baseline.jsonc @@ -0,0 +1,22 @@ +// === goToDefinition === +// === /tests/cases/fourslash/goToDefinitionOverriddenMember26.ts === +// const prop: symbol = Symbol(); +// +// abstract class A {} +// +// export class B extends A { +// /*GOTO DEF*/<|override [|[prop]|]() {}|> +// } + + // === Details === + [ + { + "kind": "method", + "name": "[prop]", + "containerName": "B", + "isLocal": false, + "isAmbient": false, + "unverified": false, + "failedAliasResolution": false + } + ] \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors6.errors.txt b/tests/baselines/reference/propertyOverridesAccessors6.errors.txt new file mode 100644 index 0000000000000..cda1185c86522 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors6.errors.txt @@ -0,0 +1,16 @@ +propertyOverridesAccessors6.ts(8,3): error TS2610: 'x' is defined as an accessor in class 'A', but is overridden here in 'C' as an instance property. + + +==== propertyOverridesAccessors6.ts (1 errors) ==== + class A { + get x() { + return 2; + } + } + class B extends A {} + class C extends B { + x = 1; + ~ +!!! error TS2610: 'x' is defined as an accessor in class 'A', but is overridden here in 'C' as an instance property. + } + \ No newline at end of file diff --git a/tests/baselines/reference/propertyOverridesAccessors6.symbols b/tests/baselines/reference/propertyOverridesAccessors6.symbols new file mode 100644 index 0000000000000..289b25db4e55e --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors6.symbols @@ -0,0 +1,24 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors6.ts] //// + +=== propertyOverridesAccessors6.ts === +class A { +>A : Symbol(A, Decl(propertyOverridesAccessors6.ts, 0, 0)) + + get x() { +>x : Symbol(A.x, Decl(propertyOverridesAccessors6.ts, 0, 9)) + + return 2; + } +} +class B extends A {} +>B : Symbol(B, Decl(propertyOverridesAccessors6.ts, 4, 1)) +>A : Symbol(A, Decl(propertyOverridesAccessors6.ts, 0, 0)) + +class C extends B { +>C : Symbol(C, Decl(propertyOverridesAccessors6.ts, 5, 20)) +>B : Symbol(B, Decl(propertyOverridesAccessors6.ts, 4, 1)) + + x = 1; +>x : Symbol(C.x, Decl(propertyOverridesAccessors6.ts, 6, 19)) +} + diff --git a/tests/baselines/reference/propertyOverridesAccessors6.types b/tests/baselines/reference/propertyOverridesAccessors6.types new file mode 100644 index 0000000000000..dc9dfd74307e4 --- /dev/null +++ b/tests/baselines/reference/propertyOverridesAccessors6.types @@ -0,0 +1,35 @@ +//// [tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors6.ts] //// + +=== propertyOverridesAccessors6.ts === +class A { +>A : A +> : ^ + + get x() { +>x : number +> : ^^^^^^ + + return 2; +>2 : 2 +> : ^ + } +} +class B extends A {} +>B : B +> : ^ +>A : A +> : ^ + +class C extends B { +>C : C +> : ^ +>B : B +> : ^ + + x = 1; +>x : number +> : ^^^^^^ +>1 : 1 +> : ^ +} + diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty10.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty10.ts new file mode 100644 index 0000000000000..43aff8ab7492e --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/accessorsOverrideProperty10.ts @@ -0,0 +1,14 @@ +// @strict: esnext +// @target: esnext +// @useDefineForClassFields: true +// @noEmit: true + +class A { + x = 1; +} +class B extends A {} +class C extends B { + get x() { + return 2; + } +} diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors6.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors6.ts new file mode 100644 index 0000000000000..9343c50daa35d --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/propertyOverridesAccessors6.ts @@ -0,0 +1,14 @@ +// @strict: esnext +// @target: esnext +// @useDefineForClassFields: true +// @noEmit: true + +class A { + get x() { + return 2; + } +} +class B extends A {} +class C extends B { + x = 1; +} diff --git a/tests/cases/fourslash/codeFixPropertyOverrideAccess4.ts b/tests/cases/fourslash/codeFixPropertyOverrideAccess4.ts new file mode 100644 index 0000000000000..fbebbed4deeec --- /dev/null +++ b/tests/cases/fourslash/codeFixPropertyOverrideAccess4.ts @@ -0,0 +1,16 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop = Symbol.for('foo'); +//// +//// class A { +//// [prop] = 1; +//// } +//// class B extends A { +//// get [prop]() { return 2; } +//// } + +verify.not.codeFixAvailable("fixPropertyOverrideAccessor"); diff --git a/tests/cases/fourslash/codeFixPropertyOverrideAccess5.ts b/tests/cases/fourslash/codeFixPropertyOverrideAccess5.ts new file mode 100644 index 0000000000000..c0e87a965b636 --- /dev/null +++ b/tests/cases/fourslash/codeFixPropertyOverrideAccess5.ts @@ -0,0 +1,29 @@ +/// + +// @strict: true + +//// class A { +//// x = 1; +//// } +//// class B extends A {} +//// class C extends B { +//// get x() { return 2; } +//// } + +verify.codeFix({ + description: `Generate 'get' and 'set' accessors`, + newFileContent: `class A { + private _x = 1; + public get x() { + return this._x; + } + public set x(value) { + this._x = value; + } +} +class B extends A {} +class C extends B { + get x() { return 2; } +}`, + index: 0 +}) diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember17.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember17.ts new file mode 100644 index 0000000000000..5b18c009aa8c5 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember17.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const entityKind = Symbol.for("drizzle:entityKind"); +//// +//// abstract class MySqlColumn { +//// static readonly /*2*/[entityKind]: string = "MySqlColumn"; +//// } +//// +//// export class MySqlVarBinary extends MySqlColumn { +//// static [|/*1*/override|] readonly [entityKind]: string = "MySqlVarBinary"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember18.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember18.ts new file mode 100644 index 0000000000000..66bd417bfe6e9 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember18.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const entityKind = Symbol.for("drizzle:entityKind"); +//// +//// abstract class MySqlColumn { +//// readonly /*2*/[entityKind]: string = "MySqlColumn"; +//// } +//// +//// export class MySqlVarBinary extends MySqlColumn { +//// [|/*1*/override|] readonly [entityKind]: string = "MySqlVarBinary"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember19.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember19.ts new file mode 100644 index 0000000000000..ab42e0c52c3df --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember19.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop = "foo" as const; +//// +//// abstract class A { +//// static readonly /*2*/[prop] = "A"; +//// } +//// +//// export class B extends A { +//// static [|/*1*/override|] readonly [prop] = "B"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember20.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember20.ts new file mode 100644 index 0000000000000..4fdaf09865eb2 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember20.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop = "foo" as const; +//// +//// abstract class A { +//// readonly /*2*/[prop] = "A"; +//// } +//// +//// export class B extends A { +//// [|/*1*/override|] readonly [prop] = "B"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember21.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember21.ts new file mode 100644 index 0000000000000..1da6ee87ee98c --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember21.ts @@ -0,0 +1,15 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop = "foo" as const; +//// +//// abstract class A {} +//// +//// export class B extends A { +//// static [|/*1*/override|] readonly [prop] = "B"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember22.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember22.ts new file mode 100644 index 0000000000000..a628e91fc0f82 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember22.ts @@ -0,0 +1,15 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop = "foo" as const; +//// +//// abstract class A {} +//// +//// export class B extends A { +//// [|/*1*/override|] readonly [prop] = "B"; +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember23.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember23.ts new file mode 100644 index 0000000000000..5dfd57b0aabff --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember23.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop: symbol = Symbol(); +//// +//// abstract class A { +//// static [prop]() {} +//// } +//// +//// export class B extends A { +//// static [|/*1*/override|] [prop]() {} +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember24.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember24.ts new file mode 100644 index 0000000000000..347c78c0478fa --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember24.ts @@ -0,0 +1,17 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop: symbol = Symbol(); +//// +//// abstract class A { +//// [prop]() {} +//// } +//// +//// export class B extends A { +//// [|/*1*/override|] [prop]() {} +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember25.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember25.ts new file mode 100644 index 0000000000000..e03dcb0c89098 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember25.ts @@ -0,0 +1,15 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop: symbol = Symbol(); +//// +//// abstract class A {} +//// +//// export class B extends A { +//// static [|/*1*/override|] [prop]() {} +//// } + +verify.baselineGoToDefinition("1"); diff --git a/tests/cases/fourslash/goToDefinitionOverriddenMember26.ts b/tests/cases/fourslash/goToDefinitionOverriddenMember26.ts new file mode 100644 index 0000000000000..2791cae54da99 --- /dev/null +++ b/tests/cases/fourslash/goToDefinitionOverriddenMember26.ts @@ -0,0 +1,15 @@ +/// + +// @strict: true +// @target: esnext +// @lib: esnext + +//// const prop: symbol = Symbol(); +//// +//// abstract class A {} +//// +//// export class B extends A { +//// [|/*1*/override|] [prop]() {} +//// } + +verify.baselineGoToDefinition("1");