-
Notifications
You must be signed in to change notification settings - Fork 12.8k
No-op string in constructor is repeated and reordered when constructor assignment is used #48671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
👉 @JoshuaKGoldberg if you feel like it |
The repetition is weird, but the reordering doesn't seem to be wrong to me at first glance; I would think that the parameters being properties implies that they must be assigned before any part of the body executes. Is there some special case for these sort of string-y statements at the start of blocks? Playground Link I guess so, because |
Yes, they're directive prologues, also sometimes callied prologue directives. I've only ever seen #29374 and https://blog.joshuakgoldberg.com/code-before-super-technical-overview/ have a good amount of backing context for how those are meant to be at the beginning of the constructor. I can probably take a look within this week! Edit: or today 😄 |
Also TIL that the spec lets you have whatever prologues you want. 😄 |
I mean, why wouldn't it? They're just strings, if the engine doesn't recognize a directive, it can just ignore it as a no-op. |
I just mean from the POV that there's nothing wrong with this code: function foo() {
console.log("Hello, world!");
console.log(Math.random());
"some random string as an expression statement";
} Because a string is an expression which can be alone in a statement. But if it's the first statement of a source file or a function body, then it's special and must not be reordered even if our emit is going to be placing things semantically "before" the block the user typed, because that changes its meaning. |
FWIW this bug applies with |
Out of curiosity, does the spec say anything about multiple directives? i.e. if I write... function foo() {
"use fooey";
"use bard";
console.log(812);
} ...are both strings required to be kept at the top of the function? |
I don't know about the spec, but at runtime it sure seems like it applies all of them: https://glot.io/snippets/g8u48lkc4o (don't ask me what runtime this site uses) |
From https://es5.github.io/#x14.1:
|
Yes, but that's specifically only about
What I was wondering about is, if there are multiple custom directives other than edit: Just read that section again, looks like the answer to my question is yes:
|
23 hours and 57 minutes from a bug report to a fix, you guys are awesome :-) Thank you! |
Signed-off-by: Babak K. Shandiz <[email protected]> diff --git a/package-lock.json b/package-lock.json index 521fb599..bd23f406 100644 --- a/package-lock.json +++ b/package-lock.json @@ -219,9 +219,9 @@ } }, "@octokit/openapi-types": { - "version": "12.10.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.0.tgz", - "integrity": "sha512-xsgA7LKuQ/2QReMZQXNlBP68ferPlqw66Jmx5/J399Cn5EgIDaHXou6Rgn1GkpDNjkPji67fTlC2rz6ABaVFKw==", + "version": "12.10.1", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.10.1.tgz", + "integrity": "sha512-P+SukKanjFY0ZhsK6wSVnQmxTP2eVPPE8OPSNuxaMYtgVzwJZgfGdwlYjf4RlRU4vLEw4ts2fsE2icG4nZ5ddQ==", "dev": true }, "@octokit/plugin-paginate-rest": { @@ -240,9 +240,9 @@ "dev": true }, "@octokit/plugin-rest-endpoint-methods": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.1.0.tgz", - "integrity": "sha512-gP/yHUY0k/uKkEqXF6tZGRhCFqZNjQ0qdh9/gVo74AJ2pc3cr1rjnW/KRw1uXUKB/H9Y0rRBCBxsLXJmQjPv3A==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-6.1.2.tgz", + "integrity": "sha512-sAfSKtLHNq0UQ2iFuI41I6m5SK6bnKFRJ5kUjDRVbmQXiRVi4aQiIcgG4cM7bt+bhSiWL4HwnTxDkWFlKeKClA==", "dev": true, "requires": { "@octokit/types": "^6.40.0", diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ce644034..4dd1b7ba 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2191,7 +2191,7 @@ namespace ts { // 1. When result is undefined, after checking for a missing "this." // 2. When result is defined function checkAndReportErrorForInvalidInitializer() { - if (propertyWithInvalidInitializer && !(getEmitScriptTarget(compilerOptions) === ScriptTarget.ESNext && useDefineForClassFields)) { + if (propertyWithInvalidInitializer && !(useDefineForClassFields && getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2022)) { // We have a match, but the reference occurred within a property initializer and the identifier also binds // to a local variable in the constructor where the code will be emitted. Note that this is actually allowed // with ESNext+useDefineForClassFields because the scope semantics are different. @@ -11896,6 +11896,9 @@ namespace ts { else if ((type as MappedType).objectFlags & ObjectFlags.Mapped) { resolveMappedTypeMembers(type as MappedType); } + else { + Debug.fail("Unhandled object type " + Debug.formatObjectFlags(type.objectFlags)); + } } else if (type.flags & TypeFlags.Union) { resolveUnionTypeMembers(type as UnionType); @@ -11903,6 +11906,9 @@ namespace ts { else if (type.flags & TypeFlags.Intersection) { resolveIntersectionTypeMembers(type as IntersectionType); } + else { + Debug.fail("Unhandled type " + Debug.formatTypeFlags(type.flags)); + } } return type as ResolvedType; } @@ -12743,12 +12749,14 @@ namespace ts { // Return list of type parameters with duplicates removed (duplicate identifier errors are generated in the actual // type checking functions). - function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): TypeParameter[] | undefined { + function getTypeParametersFromDeclaration(declaration: DeclarationWithTypeParameters): readonly TypeParameter[] | undefined { let result: TypeParameter[] | undefined; for (const node of getEffectiveTypeParameterDeclarations(declaration)) { result = appendIfUnique(result, getDeclaredTypeOfTypeParameter(node.symbol)); } - return result; + return result?.length ? result + : isFunctionDeclaration(declaration) ? getSignatureOfTypeTag(declaration)?.typeParameters + : undefined; } function symbolsToArray(symbols: SymbolTable): Symbol[] { @@ -22556,15 +22564,11 @@ namespace ts { inferFromTypeArguments(getTypeArguments(source as TypeReference), getTypeArguments(target as TypeReference), getVariances((source as TypeReference).target)); } else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) { - contravariant = !contravariant; - inferFromTypes((source as IndexType).type, (target as IndexType).type); - contravariant = !contravariant; + inferFromContravariantTypes((source as IndexType).type, (target as IndexType).type); } else if ((isLiteralType(source) || source.flags & TypeFlags.String) && target.flags & TypeFlags.Index) { const empty = createEmptyObjectTypeFromStringLiteral(source); - contravariant = !contravariant; - inferWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); - contravariant = !contravariant; + inferFromContravariantTypesWithPriority(empty, (target as IndexType).type, InferencePriority.LiteralKeyof); } else if (source.flags & TypeFlags.IndexedAccess && target.flags & TypeFlags.IndexedAccess) { inferFromTypes((source as IndexedAccessType).objectType, (target as IndexedAccessType).objectType); @@ -22577,10 +22581,7 @@ namespace ts { } else if (source.flags & TypeFlags.Substitution) { inferFromTypes((source as SubstitutionType).baseType, target); - const oldPriority = priority; - priority |= InferencePriority.SubstituteSource; - inferFromTypes((source as SubstitutionType).substitute, target); // Make substitute inference at a lower priority - priority = oldPriority; + inferWithPriority((source as SubstitutionType).substitute, target, InferencePriority.SubstituteSource); // Make substitute inference at a lower priority } else if (target.flags & TypeFlags.Conditional) { invokeOnce(source, target, inferToConditionalType); @@ -22631,6 +22632,20 @@ namespace ts { priority = savePriority; } + function inferFromContravariantTypesWithPriority(source: Type, target: Type, newPriority: InferencePriority) { + const savePriority = priority; + priority |= newPriority; + inferFromContravariantTypes(source, target); + priority = savePriority; + } + + function inferToMultipleTypesWithPriority(source: Type, targets: Type[], targetFlags: TypeFlags, newPriority: InferencePriority) { + const savePriority = priority; + priority |= newPriority; + inferToMultipleTypes(source, targets, targetFlags); + priority = savePriority; + } + function invokeOnce(source: Type, target: Type, action: (source: Type, target: Type) => void) { const key = source.id + "," + target.id; const status = visited && visited.get(key); @@ -22694,10 +22709,14 @@ namespace ts { } function inferFromContravariantTypes(source: Type, target: Type) { + contravariant = !contravariant; + inferFromTypes(source, target); + contravariant = !contravariant; + } + + function inferFromContravariantTypesIfStrictFunctionTypes(source: Type, target: Type) { if (strictFunctionTypes || priority & InferencePriority.AlwaysStrict) { - contravariant = !contravariant; - inferFromTypes(source, target); - contravariant = !contravariant; + inferFromContravariantTypes(source, target); } else { inferFromTypes(source, target); @@ -22860,11 +22879,8 @@ namespace ts { inferFromTypes(getFalseTypeFromConditionalType(source as ConditionalType), getFalseTypeFromConditionalType(target)); } else { - const savePriority = priority; - priority |= contravariant ? InferencePriority.ContravariantConditional : 0; const targetTypes = [getTrueTypeFromConditionalType(target), getFalseTypeFromConditionalType(target)]; - inferToMultipleTypes(source, targetTypes, target.flags); - priority = savePriority; + inferToMultipleTypesWithPriority(source, targetTypes, target.flags, contravariant ? InferencePriority.ContravariantConditional : 0); } } @@ -23059,7 +23075,7 @@ namespace ts { const kind = target.declaration ? target.declaration.kind : SyntaxKind.Unknown; // Once we descend into a bivariant signature we remain bivariant for all nested inferences bivariant = bivariant || kind === SyntaxKind.MethodDeclaration || kind === SyntaxKind.MethodSignature || kind === SyntaxKind.Constructor; - applyToParameterTypes(source, target, inferFromContravariantTypes); + applyToParameterTypes(source, target, inferFromContravariantTypesIfStrictFunctionTypes); bivariant = saveBivariant; applyToReturnTypes(source, target, inferFromTypes); } @@ -24613,7 +24629,7 @@ namespace ts { } // for (const _ in ref) acts as a nonnull on ref if (isVariableDeclaration(node) && node.parent.parent.kind === SyntaxKind.ForInStatement && isMatchingReference(reference, node.parent.parent.expression)) { - return getNonNullableTypeIfNeeded(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent))); + return getNonNullableTypeIfNeeded(finalizeEvolvingArrayType(getTypeFromFlowType(getTypeAtFlowNode(flow.antecedent)))); } // Assignment doesn't affect reference return undefined; @@ -30764,7 +30780,7 @@ namespace ts { let typeArguments: NodeArray<TypeNode> | undefined; - if (!isDecorator) { + if (!isDecorator && !isSuperCall(node)) { typeArguments = (node as CallExpression).typeArguments; // We already perform checking on the type arguments on the class declaration itself. @@ -33439,7 +33455,7 @@ namespace ts { error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator)); } if (node.operator === SyntaxKind.PlusToken) { - if (maybeTypeOfKind(operandType, TypeFlags.BigIntLike)) { + if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.BigIntLike)) { error(node.operand, Diagnostics.Operator_0_cannot_be_applied_to_type_1, tokenToString(node.operator), typeToString(getBaseTypeOfLiteralType(operandType))); } return numberType; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f9aa3e57..299a0fda 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5285,12 +5285,15 @@ namespace ts { function parseSuperExpression(): MemberExpression { const pos = getNodePos(); - const expression = parseTokenNode<PrimaryExpression>(); + let expression = parseTokenNode<MemberExpression>(); if (token() === SyntaxKind.LessThanToken) { const startPos = getNodePos(); const typeArguments = tryParse(parseTypeArgumentsInExpression); if (typeArguments !== undefined) { parseErrorAt(startPos, getNodePos(), Diagnostics.super_may_not_use_type_arguments); + if (!isTemplateStartOfTaggedTemplate()) { + expression = factory.createExpressionWithTypeArguments(expression, typeArguments); + } } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 52242ccb..61b982d7 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1113,7 +1113,8 @@ namespace ts { } // Add remaining statements from the body, skipping the super() call if it was found and any (already added) prologue statements - addRange(statements, visitNodes(body.statements, visitor, isStatement, superStatementIndex + 1 + prologueStatementCount)); + const start = superStatementIndex >= 0 ? superStatementIndex + 1 : prologueStatementCount; + addRange(statements, visitNodes(body.statements, visitor, isStatement, start)); // End the lexical environment. statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment()); diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index f2f0c030..229620a1 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -932,6 +932,12 @@ namespace ts { /** * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + * + * This does *not* return type parameters from a jsdoc reference to a generic type, eg + * + * type Id = <T>(x: T) => T + * /** @type {Id} / + * function id(x) { return x } */ export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[] { if (isJSDocSignature(node)) { diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index 12470880..1654c937 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -13828,11 +13828,11 @@ declare var SubmitEvent: { * Available only in secure contexts. */ interface SubtleCrypto { - decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>; deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>; deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise<ArrayBuffer>; - encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>; exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>; exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>; generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>; diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 343cb94c..b88d6b74 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -2988,11 +2988,11 @@ declare var StorageManager: { * Available only in secure contexts. */ interface SubtleCrypto { - decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + decrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>; deriveBits(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>; deriveKey(algorithm: AlgorithmIdentifier | EcdhKeyDeriveParams | HkdfParams | Pbkdf2Params, baseKey: CryptoKey, derivedKeyType: AlgorithmIdentifier | AesDerivedKeyParams | HmacImportParams | HkdfParams | Pbkdf2Params, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>; digest(algorithm: AlgorithmIdentifier, data: BufferSource): Promise<ArrayBuffer>; - encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<any>; + encrypt(algorithm: AlgorithmIdentifier | RsaOaepParams | AesCtrParams | AesCbcParams | AesGcmParams, key: CryptoKey, data: BufferSource): Promise<ArrayBuffer>; exportKey(format: "jwk", key: CryptoKey): Promise<JsonWebKey>; exportKey(format: Exclude<KeyFormat, "jwk">, key: CryptoKey): Promise<ArrayBuffer>; generateKey(algorithm: RsaHashedKeyGenParams | EcKeyGenParams, extractable: boolean, keyUsages: ReadonlyArray<KeyUsage>): Promise<CryptoKeyPair>; diff --git a/src/server/session.ts b/src/server/session.ts index 0fe57694..d0aaf189 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -344,6 +344,8 @@ namespace ts.server { function getDefinitionLocation(defaultProject: Project, initialLocation: DocumentPosition, isForRename: boolean): DocumentPosition | undefined { const infos = defaultProject.getLanguageService().getDefinitionAtPosition(initialLocation.fileName, initialLocation.pos, /*searchOtherFilesOnly*/ false, /*stopAtAlias*/ isForRename); const info = infos && firstOrUndefined(infos); + // Note that the value of `isLocal` may depend on whether or not the checker has run on the containing file + // (implying that FAR cascading behavior may depend on request order) return info && !info.isLocal ? { fileName: info.fileName, pos: info.textSpan.start } : undefined; } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index a4c11fd5..2f5c8703 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -143,7 +143,7 @@ namespace ts.codefix { break; } - const signatures = checker.getSignaturesOfType(type, SignatureKind.Call); + const signatures = type.isUnion() ? flatMap(type.types, t => t.getCallSignatures()) : type.getCallSignatures(); if (!some(signatures)) { break; } diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index e85246e9..257531c1 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -357,8 +357,12 @@ namespace ts.JsDoc { } const { commentOwner, parameters, hasReturn } = commentOwnerInfo; - const commentOwnerJSDoc = hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? lastOrUndefined(commentOwner.jsDoc) : undefined; - if (commentOwner.getStart(sourceFile) < position || commentOwnerJSDoc && commentOwnerJSDoc !== existingDocComment) { + const commentOwnerJsDoc = hasJSDocNodes(commentOwner) && commentOwner.jsDoc ? commentOwner.jsDoc : undefined; + const lastJsDoc = lastOrUndefined(commentOwnerJsDoc); + if (commentOwner.getStart(sourceFile) < position + || lastJsDoc + && existingDocComment + && lastJsDoc !== existingDocComment) { return undefined; } @@ -378,7 +382,11 @@ namespace ts.JsDoc { // * if the caret was directly in front of the object, then we add an extra line and indentation. const openComment = "/**"; const closeComment = " */"; - if (tags) { + + // If any of the existing jsDoc has tags, ignore adding new ones. + const hasTag = (commentOwnerJsDoc || []).some(jsDoc => !!jsDoc.tags); + + if (tags && !hasTag) { const preamble = openComment + newLine + indentationStr + " * "; const endLine = tokenStart === position ? newLine + indentationStr : ""; const result = preamble + newLine + tags + indentationStr + closeComment + endLine; diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 6b2ec866..67435b47 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -551,7 +551,7 @@ namespace ts.refactor.extractSymbol { const savedPermittedJumps = permittedJumps; switch (node.kind) { case SyntaxKind.IfStatement: - permittedJumps = PermittedJumps.None; + permittedJumps &= ~PermittedJumps.Return; break; case SyntaxKind.TryStatement: // forbid all jumps inside try blocks diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index a32022f9..cb7260f6 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -167,9 +167,9 @@ namespace ts.Completions.StringCompletions { case SyntaxKind.LiteralType: { const grandParent = walkUpParentheses(parent.parent); switch (grandParent.kind) { + case SyntaxKind.ExpressionWithTypeArguments: case SyntaxKind.TypeReference: { - const typeReference = grandParent as TypeReferenceNode; - const typeArgument = findAncestor(parent, n => n.parent === typeReference) as LiteralTypeNode; + const typeArgument = findAncestor(parent, n => n.parent === grandParent) as LiteralTypeNode; if (typeArgument) { return { kind: StringLiteralCompletionKind.Types, types: getStringLiteralTypes(typeChecker.getTypeArgumentConstraint(typeArgument)), isNewIdentifier: false }; } diff --git a/src/services/types.ts b/src/services/types.ts index 27c7616b..b9015a73 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -1045,7 +1045,12 @@ namespace ts { containerKind: ScriptElementKind; containerName: string; unverified?: boolean; - /* @internal */ isLocal?: boolean; + /** @internal + * Initially, this value is determined syntactically, but it is updated by the checker to cover + * cases like declarations that are exported in subsequent statements. As a result, the value + * may be "incomplete" if this span has yet to be checked. + */ + isLocal?: boolean; /* @internal */ isAmbient?: boolean; /* @internal */ failedAliasResolution?: boolean; } diff --git a/src/testRunner/compilerRunner.ts b/src/testRunner/compilerRunner.ts index 1d320d66..a6c67a17 100644 --- a/src/testRunner/compilerRunner.ts +++ b/src/testRunner/compilerRunner.ts @@ -141,7 +141,8 @@ namespace Harness { "preserveConstEnums", "skipLibCheck", "exactOptionalPropertyTypes", - "useUnknownInCatchVariables" + "useDefineForClassFields", + "useUnknownInCatchVariables", ]; private fileName: string; private justName: string; diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 23bfc30e..bbc5c384 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4464,6 +4464,12 @@ declare namespace ts { /** * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + * + * This does *not* return type parameters from a jsdoc reference to a generic type, eg + * + * type Id = <T>(x: T) => T + * /** @type {Id} / + * function id(x) { return x } */ function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 18ef4ee2..f9e5f2d0 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4464,6 +4464,12 @@ declare namespace ts { /** * Gets the effective type parameters. If the node was parsed in a * JavaScript file, gets the type parameters from the `@template` tag from JSDoc. + * + * This does *not* return type parameters from a jsdoc reference to a generic type, eg + * + * type Id = <T>(x: T) => T + * /** @type {Id} / + * function id(x) { return x } */ function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): readonly TypeParameterDeclaration[]; function getEffectiveConstraintOfTypeParameter(node: TypeParameterDeclaration): TypeNode | undefined; diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt new file mode 100644 index 00000000..d214ea13 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js new file mode 100644 index 00000000..9591c174 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).js @@ -0,0 +1,15 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + this.p = x; + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols new file mode 100644 index 00000000..78c02088 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types new file mode 100644 index 00000000..20cff567 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=false).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt new file mode 100644 index 00000000..d214ea13 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js new file mode 100644 index 00000000..c2f4708c --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).js @@ -0,0 +1,20 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + Object.defineProperty(this, "p", { + enumerable: true, + configurable: true, + writable: true, + value: x + }); + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols new file mode 100644 index 00000000..78c02088 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types new file mode 100644 index 00000000..20cff567 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=es2017,usedefineforclassfields=true).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt new file mode 100644 index 00000000..d214ea13 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).errors.txt @@ -0,0 +1,12 @@ +tests/cases/compiler/classMemberInitializerScoping2.ts(3,9): error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + + +==== tests/cases/compiler/classMemberInitializerScoping2.ts (1 errors) ==== + const x = 1 + class C { + p = x + ~ +!!! error TS2301: Initializer of instance member variable 'p' cannot reference identifier 'x' declared in the constructor. + constructor(x: string) { } + } + \ No newline at end of file diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js new file mode 100644 index 00000000..9591c174 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).js @@ -0,0 +1,15 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + constructor(x) { + this.p = x; + } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols new file mode 100644 index 00000000..78c02088 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).symbols @@ -0,0 +1,14 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types new file mode 100644 index 00000000..20cff567 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=false).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : any +>x : any + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js new file mode 100644 index 00000000..2d008f66 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).js @@ -0,0 +1,14 @@ +//// [classMemberInitializerScoping2.ts] +const x = 1 +class C { + p = x + constructor(x: string) { } +} + + +//// [classMemberInitializerScoping2.js] +const x = 1; +class C { + p = x; + constructor(x) { } +} diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols new file mode 100644 index 00000000..cf486c1e --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + +class C { +>C : Symbol(C, Decl(classMemberInitializerScoping2.ts, 0, 11)) + + p = x +>p : Symbol(C.p, Decl(classMemberInitializerScoping2.ts, 1, 9)) +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 0, 5)) + + constructor(x: string) { } +>x : Symbol(x, Decl(classMemberInitializerScoping2.ts, 3, 16)) +} + diff --git a/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types new file mode 100644 index 00000000..9e045ca5 --- /dev/null +++ b/tests/baselines/reference/classMemberInitializerScoping2(target=esnext,usedefineforclassfields=true).types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/classMemberInitializerScoping2.ts === +const x = 1 +>x : 1 +>1 : 1 + +class C { +>C : C + + p = x +>p : number +>x : 1 + + constructor(x: string) { } +>x : string +} + diff --git a/tests/baselines/reference/evolvingArrayResolvedAssert.errors.txt b/tests/baselines/reference/evolvingArrayResolvedAssert.errors.txt new file mode 100644 index 00000000..487ffa3a --- /dev/null +++ b/tests/baselines/reference/evolvingArrayResolvedAssert.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/evolvingArrayResolvedAssert.ts(1,5): error TS7034: Variable 'C' implicitly has type 'any[]' in some locations where its type cannot be determined. +tests/cases/compiler/evolvingArrayResolvedAssert.ts(2,15): error TS7005: Variable 'C' implicitly has an 'any[]' type. +tests/cases/compiler/evolvingArrayResolvedAssert.ts(3,9): error TS7005: Variable 'C' implicitly has an 'any[]' type. + + +==== tests/cases/compiler/evolvingArrayResolvedAssert.ts (3 errors) ==== + var C = []; + ~ +!!! error TS7034: Variable 'C' implicitly has type 'any[]' in some locations where its type cannot be determined. + for (var a in C) { + ~ +!!! error TS7005: Variable 'C' implicitly has an 'any[]' type. + if (C.hasOwnProperty(a)) { + ~ +!!! error TS7005: Variable 'C' implicitly has an 'any[]' type. + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/evolvingArrayResolvedAssert.js b/tests/baselines/reference/evolvingArrayResolvedAssert.js new file mode 100644 index 00000000..4cae93bb --- /dev/null +++ b/tests/baselines/reference/evolvingArrayResolvedAssert.js @@ -0,0 +1,15 @@ +//// [evolvingArrayResolvedAssert.ts] +var C = []; +for (var a in C) { + if (C.hasOwnProperty(a)) { + } +} + + +//// [evolvingArrayResolvedAssert.js] +"use strict"; +var C = []; +for (var a in C) { + if (C.hasOwnProperty(a)) { + } +} diff --git a/tests/baselines/reference/evolvingArrayResolvedAssert.symbols b/tests/baselines/reference/evolvingArrayResolvedAssert.symbols new file mode 100644 index 00000000..8d52f9e5 --- /dev/null +++ b/tests/baselines/reference/evolvingArrayResolvedAssert.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/evolvingArrayResolvedAssert.ts === +var C = []; +>C : Symbol(C, Decl(evolvingArrayResolvedAssert.ts, 0, 3)) + +for (var a in C) { +>a : Symbol(a, Decl(evolvingArrayResolvedAssert.ts, 1, 8)) +>C : Symbol(C, Decl(evolvingArrayResolvedAssert.ts, 0, 3)) + + if (C.hasOwnProperty(a)) { +>C.hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.es5.d.ts, --, --)) +>C : Symbol(C, Decl(evolvingArrayResolvedAssert.ts, 0, 3)) +>hasOwnProperty : Symbol(Object.hasOwnProperty, Decl(lib.es5.d.ts, --, --)) +>a : Symbol(a, Decl(evolvingArrayResolvedAssert.ts, 1, 8)) + } +} + diff --git a/tests/baselines/reference/evolvingArrayResolvedAssert.types b/tests/baselines/reference/evolvingArrayResolvedAssert.types new file mode 100644 index 00000000..b0524c27 --- /dev/null +++ b/tests/baselines/reference/evolvingArrayResolvedAssert.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/evolvingArrayResolvedAssert.ts === +var C = []; +>C : any[] +>[] : never[] + +for (var a in C) { +>a : string +>C : any[] + + if (C.hasOwnProperty(a)) { +>C.hasOwnProperty(a) : boolean +>C.hasOwnProperty : (v: PropertyKey) => boolean +>C : any[] +>hasOwnProperty : (v: PropertyKey) => boolean +>a : string + } +} + diff --git a/tests/baselines/reference/numberVsBigIntOperations.errors.txt b/tests/baselines/reference/numberVsBigIntOperations.errors.txt index 42e49eb3..e5ad663d 100644 --- a/tests/baselines/reference/numberVsBigIntOperations.errors.txt +++ b/tests/baselines/reference/numberVsBigIntOperations.errors.txt @@ -62,9 +62,11 @@ tests/cases/compiler/numberVsBigIntOperations.ts(61,1): error TS2365: Operator ' tests/cases/compiler/numberVsBigIntOperations.ts(70,2): error TS2736: Operator '+' cannot be applied to type 'number | bigint'. tests/cases/compiler/numberVsBigIntOperations.ts(86,7): error TS1155: 'const' declarations must be initialized. tests/cases/compiler/numberVsBigIntOperations.ts(93,7): error TS1155: 'const' declarations must be initialized. +tests/cases/compiler/numberVsBigIntOperations.ts(98,6): error TS2736: Operator '+' cannot be applied to type 'S'. +tests/cases/compiler/numberVsBigIntOperations.ts(99,5): error TS2365: Operator '+' cannot be applied to types 'number' and 'S'. -==== tests/cases/compiler/numberVsBigIntOperations.ts (64 errors) ==== +==== tests/cases/compiler/numberVsBigIntOperations.ts (66 errors) ==== // Cannot mix bigints and numbers let bigInt = 1n, num = 2; bigInt = 1n; bigInt = 2; num = 1n; num = 2; @@ -286,4 +288,15 @@ tests/cases/compiler/numberVsBigIntOperations.ts(93,7): error TS1155: 'const' de const bigZeroOrOne: 0n | 1; ~~~~~~~~~~~~ !!! error TS1155: 'const' declarations must be initialized. - if (bigZeroOrOne) isOne(bigZeroOrOne); \ No newline at end of file + if (bigZeroOrOne) isOne(bigZeroOrOne); + + type NumberOrBigint = number | bigint; + function getKey<S extends NumberOrBigint>(key: S) { + +key; // should error + ~~~ +!!! error TS2736: Operator '+' cannot be applied to type 'S'. + 0 + key; // should error + ~~~~~~~ +!!! error TS2365: Operator '+' cannot be applied to types 'number' and 'S'. + } + \ No newline at end of file diff --git a/tests/baselines/reference/numberVsBigIntOperations.js b/tests/baselines/reference/numberVsBigIntOperations.js index 9d8a4920..3558a073 100644 --- a/tests/baselines/reference/numberVsBigIntOperations.js +++ b/tests/baselines/reference/numberVsBigIntOperations.js @@ -92,7 +92,14 @@ else isNumber(zeroOrBigOne); const isOne = (x: 1 | 1n) => x; if (zeroOrBigOne) isOne(zeroOrBigOne); const bigZeroOrOne: 0n | 1; -if (bigZeroOrOne) isOne(bigZeroOrOne); +if (bigZeroOrOne) isOne(bigZeroOrOne); + +type NumberOrBigint = number | bigint; +function getKey<S extends NumberOrBigint>(key: S) { + +key; // should error + 0 + key; // should error +} + //// [numberVsBigIntOperations.js] // Cannot mix bigints and numbers @@ -272,3 +279,7 @@ if (zeroOrBigOne) const bigZeroOrOne; if (bigZeroOrOne) isOne(bigZeroOrOne); +function getKey(key) { + +key; // should error + 0 + key; // should error +} diff --git a/tests/baselines/reference/numberVsBigIntOperations.symbols b/tests/baselines/reference/numberVsBigIntOperations.symbols index 1b164afb..e9f91b8d 100644 --- a/tests/baselines/reference/numberVsBigIntOperations.symbols +++ b/tests/baselines/reference/numberVsBigIntOperations.symbols @@ -348,3 +348,20 @@ if (bigZeroOrOne) isOne(bigZeroOrOne); >isOne : Symbol(isOne, Decl(numberVsBigIntOperations.ts, 90, 5)) >bigZeroOrOne : Symbol(bigZeroOrOne, Decl(numberVsBigIntOperations.ts, 92, 5)) +type NumberOrBigint = number | bigint; +>NumberOrBigint : Symbol(NumberOrBigint, Decl(numberVsBigIntOperations.ts, 93, 38)) + +function getKey<S extends NumberOrBigint>(key: S) { +>getKey : Symbol(getKey, Decl(numberVsBigIntOperations.ts, 95, 38)) +>S : Symbol(S, Decl(numberVsBigIntOperations.ts, 96, 16)) +>NumberOrBigint : Symbol(NumberOrBigint, Decl(numberVsBigIntOperations.ts, 93, 38)) +>key : Symbol(key, Decl(numberVsBigIntOperations.ts, 96, 42)) +>S : Symbol(S, Decl(numberVsBigIntOperations.ts, 96, 16)) + + +key; // should error +>key : Symbol(key, Decl(numberVsBigIntOperations.ts, 96, 42)) + + 0 + key; // should error +>key : Symbol(key, Decl(numberVsBigIntOperations.ts, 96, 42)) +} + diff --git a/tests/baselines/reference/numberVsBigIntOperations.types b/tests/baselines/reference/numberVsBigIntOperations.types index ddb81030..4fc625d3 100644 --- a/tests/baselines/reference/numberVsBigIntOperations.types +++ b/tests/baselines/reference/numberVsBigIntOperations.types @@ -727,3 +727,20 @@ if (bigZeroOrOne) isOne(bigZeroOrOne); >isOne : (x: 1n | 1) => 1n | 1 >bigZeroOrOne : 1 +type NumberOrBigint = number | bigint; +>NumberOrBigint : number | bigint + +function getKey<S extends NumberOrBigint>(key: S) { +>getKey : <S extends NumberOrBigint>(key: S) => void +>key : S + + +key; // should error +>+key : number +>key : S + + 0 + key; // should error +>0 + key : any +>0 : 0 +>key : S +} + diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js index d952cf8b..c4232420 100644 --- a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.js @@ -1,6 +1,8 @@ //// [parameterPropertyInConstructorWithPrologues.ts] // https://github.com/microsoft/TypeScript/issues/48671 +class C {} + class Foo1 { constructor(private A: string) { "ngInject1"; @@ -43,10 +45,65 @@ class Foo6 { console.log("hi"); } } + +class Foo7 extends C { + constructor( + private member: boolean, + ) { + "ngInject1"; + super(); + console.log("hi"); + } +} + +class Foo8 extends C { + constructor( + private member: boolean, + ) { + "ngInject1"; + super(); + this.m(); + console.log("hi"); + } + + m() {} +} + +class Foo9 extends C { + constructor() { + "ngInject1"; + "ngInject2"; + super(); + this.m(); + console.log("hi"); + } + + m() {} +} //// [parameterPropertyInConstructorWithPrologues.js] // https://github.com/microsoft/TypeScript/issues/48671 +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var C = /** @class */ (function () { + function C() { + } + return C; +}()); var Foo1 = /** @class */ (function () { function Foo1(A) { "ngInject1"; @@ -102,3 +159,40 @@ var Foo6 = /** @class */ (function () { } return Foo6; }()); +var Foo7 = /** @class */ (function (_super) { + __extends(Foo7, _super); + function Foo7(member) { + "ngInject1"; + var _this = _super.call(this) || this; + _this.member = member; + console.log("hi"); + return _this; + } + return Foo7; +}(C)); +var Foo8 = /** @class */ (function (_super) { + __extends(Foo8, _super); + function Foo8(member) { + "ngInject1"; + var _this = _super.call(this) || this; + _this.member = member; + _this.m(); + console.log("hi"); + return _this; + } + Foo8.prototype.m = function () { }; + return Foo8; +}(C)); +var Foo9 = /** @class */ (function (_super) { + __extends(Foo9, _super); + function Foo9() { + "ngInject1"; + "ngInject2"; + var _this = _super.call(this) || this; + _this.m(); + console.log("hi"); + return _this; + } + Foo9.prototype.m = function () { }; + return Foo9; +}(C)); diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols index 582bfd76..7e2adfcb 100644 --- a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.symbols @@ -1,22 +1,25 @@ === tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts === // https://github.com/microsoft/TypeScript/issues/48671 +class C {} +>C : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + class Foo1 { ->Foo1 : Symbol(Foo1, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) +>Foo1 : Symbol(Foo1, Decl(parameterPropertyInConstructorWithPrologues.ts, 2, 10)) constructor(private A: string) { ->A : Symbol(Foo1.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 3, 14)) +>A : Symbol(Foo1.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 5, 14)) "ngInject1"; } } class Foo2 { ->Foo2 : Symbol(Foo2, Decl(parameterPropertyInConstructorWithPrologues.ts, 6, 1)) +>Foo2 : Symbol(Foo2, Decl(parameterPropertyInConstructorWithPrologues.ts, 8, 1)) constructor(private A: string, private B: string) { ->A : Symbol(Foo2.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 9, 14)) ->B : Symbol(Foo2.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 9, 32)) +>A : Symbol(Foo2.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 11, 14)) +>B : Symbol(Foo2.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 11, 32)) "ngInject1"; "ngInject2"; @@ -24,12 +27,12 @@ class Foo2 { } class Foo3 { ->Foo3 : Symbol(Foo3, Decl(parameterPropertyInConstructorWithPrologues.ts, 13, 1)) +>Foo3 : Symbol(Foo3, Decl(parameterPropertyInConstructorWithPrologues.ts, 15, 1)) constructor(private A: string, private B: string, private C: string) { ->A : Symbol(Foo3.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 14)) ->B : Symbol(Foo3.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 32)) ->C : Symbol(Foo3.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 16, 51)) +>A : Symbol(Foo3.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 18, 14)) +>B : Symbol(Foo3.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 18, 32)) +>C : Symbol(Foo3.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 18, 51)) "ngInject1"; "ngInject2"; @@ -37,10 +40,10 @@ class Foo3 { } class Foo4 { ->Foo4 : Symbol(Foo4, Decl(parameterPropertyInConstructorWithPrologues.ts, 20, 1)) +>Foo4 : Symbol(Foo4, Decl(parameterPropertyInConstructorWithPrologues.ts, 22, 1)) constructor(private A: string) { ->A : Symbol(Foo4.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 23, 14)) +>A : Symbol(Foo4.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 25, 14)) "ngInject1"; console.log("hi"); @@ -51,11 +54,11 @@ class Foo4 { } class Foo5 { ->Foo5 : Symbol(Foo5, Decl(parameterPropertyInConstructorWithPrologues.ts, 27, 1)) +>Foo5 : Symbol(Foo5, Decl(parameterPropertyInConstructorWithPrologues.ts, 29, 1)) constructor(private A: string, private B: string) { ->A : Symbol(Foo5.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 30, 14)) ->B : Symbol(Foo5.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 30, 32)) +>A : Symbol(Foo5.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 32, 14)) +>B : Symbol(Foo5.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 32, 32)) "ngInject1"; "ngInject2"; @@ -67,19 +70,92 @@ class Foo5 { } class Foo6 { ->Foo6 : Symbol(Foo6, Decl(parameterPropertyInConstructorWithPrologues.ts, 35, 1)) +>Foo6 : Symbol(Foo6, Decl(parameterPropertyInConstructorWithPrologues.ts, 37, 1)) constructor(private A: string, private B: string, private C: string) { ->A : Symbol(Foo6.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 14)) ->B : Symbol(Foo6.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 32)) ->C : Symbol(Foo6.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 38, 51)) +>A : Symbol(Foo6.A, Decl(parameterPropertyInConstructorWithPrologues.ts, 40, 14)) +>B : Symbol(Foo6.B, Decl(parameterPropertyInConstructorWithPrologues.ts, 40, 32)) +>C : Symbol(Foo6.C, Decl(parameterPropertyInConstructorWithPrologues.ts, 40, 51)) + + "ngInject1"; + "ngInject2"; + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + +class Foo7 extends C { +>Foo7 : Symbol(Foo7, Decl(parameterPropertyInConstructorWithPrologues.ts, 45, 1)) +>C : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + constructor( + private member: boolean, +>member : Symbol(Foo7.member, Decl(parameterPropertyInConstructorWithPrologues.ts, 48, 14)) + + ) { + "ngInject1"; + super(); +>super : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } +} + +class Foo8 extends C { +>Foo8 : Symbol(Foo8, Decl(parameterPropertyInConstructorWithPrologues.ts, 55, 1)) +>C : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + constructor( + private member: boolean, +>member : Symbol(Foo8.member, Decl(parameterPropertyInConstructorWithPrologues.ts, 58, 14)) + + ) { + "ngInject1"; + super(); +>super : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + this.m(); +>this.m : Symbol(Foo8.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 65, 3)) +>this : Symbol(Foo8, Decl(parameterPropertyInConstructorWithPrologues.ts, 55, 1)) +>m : Symbol(Foo8.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 65, 3)) + + console.log("hi"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + } + + m() {} +>m : Symbol(Foo8.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 65, 3)) +} + +class Foo9 extends C { +>Foo9 : Symbol(Foo9, Decl(parameterPropertyInConstructorWithPrologues.ts, 68, 1)) +>C : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + constructor() { "ngInject1"; "ngInject2"; + super(); +>super : Symbol(C, Decl(parameterPropertyInConstructorWithPrologues.ts, 0, 0)) + + this.m(); +>this.m : Symbol(Foo9.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 77, 3)) +>this : Symbol(Foo9, Decl(parameterPropertyInConstructorWithPrologues.ts, 68, 1)) +>m : Symbol(Foo9.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 77, 3)) + console.log("hi"); >console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) >console : Symbol(console, Decl(lib.dom.d.ts, --, --)) >log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) } + + m() {} +>m : Symbol(Foo9.m, Decl(parameterPropertyInConstructorWithPrologues.ts, 77, 3)) } diff --git a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types index 2f676ee3..857196e3 100644 --- a/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types +++ b/tests/baselines/reference/parameterPropertyInConstructorWithPrologues.types @@ -1,6 +1,9 @@ === tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts === // https://github.com/microsoft/TypeScript/issues/48671 +class C {} +>C : C + class Foo1 { >Foo1 : Foo1 @@ -106,3 +109,95 @@ class Foo6 { } } +class Foo7 extends C { +>Foo7 : Foo7 +>C : C + + constructor( + private member: boolean, +>member : boolean + + ) { + "ngInject1"; +>"ngInject1" : "ngInject1" + + super(); +>super() : void +>super : typeof C + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } +} + +class Foo8 extends C { +>Foo8 : Foo8 +>C : C + + constructor( + private member: boolean, +>member : boolean + + ) { + "ngInject1"; +>"ngInject1" : "ngInject1" + + super(); +>super() : void +>super : typeof C + + this.m(); +>this.m() : void +>this.m : () => void +>this : this +>m : () => void + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } + + m() {} +>m : () => void +} + +class Foo9 extends C { +>Foo9 : Foo9 +>C : C + + constructor() { + "ngInject1"; +>"ngInject1" : "ngInject1" + + "ngInject2"; +>"ngInject2" : "ngInject2" + + super(); +>super() : void +>super : typeof C + + this.m(); +>this.m() : void +>this.m : () => void +>this : this +>m : () => void + + console.log("hi"); +>console.log("hi") : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>"hi" : "hi" + } + + m() {} +>m : () => void +} + diff --git a/tests/baselines/reference/parserSuperExpression2.symbols b/tests/baselines/reference/parserSuperExpression2.symbols index c382e548..47fff63a 100644 --- a/tests/baselines/reference/parserSuperExpression2.symbols +++ b/tests/baselines/reference/parserSuperExpression2.symbols @@ -6,5 +6,6 @@ class C { >M : Symbol(C.M, Decl(parserSuperExpression2.ts, 0, 9)) super<T>(0); +>T : Symbol(T) } } diff --git a/tests/baselines/reference/superWithTypeArgument.symbols b/tests/baselines/reference/superWithTypeArgument.symbols index 50990b48..eeb59199 100644 --- a/tests/baselines/reference/superWithTypeArgument.symbols +++ b/tests/baselines/reference/superWithTypeArgument.symbols @@ -12,5 +12,6 @@ class D<T> extends C { constructor() { super<T>(); >super : Symbol(C, Decl(superWithTypeArgument.ts, 0, 0)) +>T : Symbol(T, Decl(superWithTypeArgument.ts, 4, 8)) } } diff --git a/tests/baselines/reference/superWithTypeArgument2.symbols b/tests/baselines/reference/superWithTypeArgument2.symbols index 35a371cd..c42450e8 100644 --- a/tests/baselines/reference/superWithTypeArgument2.symbols +++ b/tests/baselines/reference/superWithTypeArgument2.symbols @@ -19,6 +19,7 @@ class D<T> extends C<T> { super<T>(x); >super : Symbol(C, Decl(superWithTypeArgument2.ts, 0, 0)) +>T : Symbol(T, Decl(superWithTypeArgument2.ts, 4, 8)) >x : Symbol(x, Decl(superWithTypeArgument2.ts, 5, 16)) } } diff --git a/tests/baselines/reference/superWithTypeArgument3.symbols b/tests/baselines/reference/superWithTypeArgument3.symbols index a596264a..9a6ff935 100644 --- a/tests/baselines/reference/superWithTypeArgument3.symbols +++ b/tests/baselines/reference/superWithTypeArgument3.symbols @@ -23,6 +23,7 @@ class D<T> extends C<T> { constructor() { super<T>(); >super : Symbol(C, Decl(superWithTypeArgument3.ts, 0, 0)) +>T : Symbol(T, Decl(superWithTypeArgument3.ts, 5, 8)) } bar() { >bar : Symbol(D.bar, Decl(superWithTypeArgument3.ts, 8, 5)) diff --git a/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.js b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.js new file mode 100644 index 00000000..2ae16666 --- /dev/null +++ b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.js @@ -0,0 +1,45 @@ +//// [typeTagOnFunctionReferencesGeneric.js] +/** + * @typedef {<T>(m : T) => T} IFn + */ + +/**@type {IFn}*/ +export function inJs(l) { + return l; +} +inJs(1); // lints error. Why? + +/**@type {IFn}*/ +const inJsArrow = (j) => { + return j; +} +inJsArrow(2); // no error gets linted as expected + + +//// [typeTagOnFunctionReferencesGeneric.js] +"use strict"; +/** + * @typedef {<T>(m : T) => T} IFn + */ +exports.__esModule = true; +exports.inJs = void 0; +/**@type {IFn}*/ +function inJs(l) { + return l; +} +exports.inJs = inJs; +inJs(1); // lints error. Why? +/**@type {IFn}*/ +var inJsArrow = function (j) { + return j; +}; +inJsArrow(2); // no error gets linted as expected + + +//// [typeTagOnFunctionReferencesGeneric.d.ts] +/** + * @typedef {<T>(m : T) => T} IFn + */ +/**@type {IFn}*/ +export function inJs<T>(l: T): T; +export type IFn = <T>(m: T) => T; diff --git a/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.symbols b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.symbols new file mode 100644 index 00000000..10e9e580 --- /dev/null +++ b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.symbols @@ -0,0 +1,27 @@ +=== tests/cases/conformance/salsa/typeTagOnFunctionReferencesGeneric.js === +/** + * @typedef {<T>(m : T) => T} IFn + */ + +/**@type {IFn}*/ +export function inJs(l) { +>inJs : Symbol(inJs, Decl(typeTagOnFunctionReferencesGeneric.js, 0, 0)) +>l : Symbol(l, Decl(typeTagOnFunctionReferencesGeneric.js, 5, 21)) + + return l; +>l : Symbol(l, Decl(typeTagOnFunctionReferencesGeneric.js, 5, 21)) +} +inJs(1); // lints error. Why? +>inJs : Symbol(inJs, Decl(typeTagOnFunctionReferencesGeneric.js, 0, 0)) + +/**@type {IFn}*/ +const inJsArrow = (j) => { +>inJsArrow : Symbol(inJsArrow, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 5)) +>j : Symbol(j, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 19)) + + return j; +>j : Symbol(j, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 19)) +} +inJsArrow(2); // no error gets linted as expected +>inJsArrow : Symbol(inJsArrow, Decl(typeTagOnFunctionReferencesGeneric.js, 11, 5)) + diff --git a/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.types b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.types new file mode 100644 index 00000000..eb4f7183 --- /dev/null +++ b/tests/baselines/reference/typeTagOnFunctionReferencesGeneric.types @@ -0,0 +1,32 @@ +=== tests/cases/conformance/salsa/typeTagOnFunctionReferencesGeneric.js === +/** + * @typedef {<T>(m : T) => T} IFn + */ + +/**@type {IFn}*/ +export function inJs(l) { +>inJs : <T>(l: T) => T +>l : T + + return l; +>l : T +} +inJs(1); // lints error. Why? +>inJs(1) : 1 +>inJs : <T>(l: T) => T +>1 : 1 + +/**@type {IFn}*/ +const inJsArrow = (j) => { +>inJsArrow : IFn +>(j) => { return j;} : <T>(j: T) => T +>j : T + + return j; +>j : T +} +inJsArrow(2); // no error gets linted as expected +>inJsArrow(2) : 2 +>inJsArrow : IFn +>2 : 2 + diff --git a/tests/cases/compiler/classMemberInitializerScoping2.ts b/tests/cases/compiler/classMemberInitializerScoping2.ts new file mode 100644 index 00000000..583d9f03 --- /dev/null +++ b/tests/cases/compiler/classMemberInitializerScoping2.ts @@ -0,0 +1,8 @@ +// @target: es2017,esnext +// @useDefineForClassFields: true,false + +const x = 1 +class C { + p = x + constructor(x: string) { } +} diff --git a/tests/cases/compiler/evolvingArrayResolvedAssert.ts b/tests/cases/compiler/evolvingArrayResolvedAssert.ts new file mode 100644 index 00000000..7ba37947 --- /dev/null +++ b/tests/cases/compiler/evolvingArrayResolvedAssert.ts @@ -0,0 +1,7 @@ +// @strict: true + +var C = []; +for (var a in C) { + if (C.hasOwnProperty(a)) { + } +} diff --git a/tests/cases/compiler/numberVsBigIntOperations.ts b/tests/cases/compiler/numberVsBigIntOperations.ts index 74b1cea8..f53b3a14 100644 --- a/tests/cases/compiler/numberVsBigIntOperations.ts +++ b/tests/cases/compiler/numberVsBigIntOperations.ts @@ -93,4 +93,10 @@ else isNumber(zeroOrBigOne); const isOne = (x: 1 | 1n) => x; if (zeroOrBigOne) isOne(zeroOrBigOne); const bigZeroOrOne: 0n | 1; -if (bigZeroOrOne) isOne(bigZeroOrOne); \ No newline at end of file +if (bigZeroOrOne) isOne(bigZeroOrOne); + +type NumberOrBigint = number | bigint; +function getKey<S extends NumberOrBigint>(key: S) { + +key; // should error + 0 + key; // should error +} diff --git a/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts b/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts index aa6acde1..45b20b36 100644 --- a/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts +++ b/tests/cases/compiler/parameterPropertyInConstructorWithPrologues.ts @@ -1,5 +1,7 @@ // https://github.com/microsoft/TypeScript/issues/48671 +class C {} + class Foo1 { constructor(private A: string) { "ngInject1"; @@ -42,3 +44,38 @@ class Foo6 { …
Bug Report
The TypeScript code
when compiled with TS 4.6.2 yields:
when compiled with TS 4.5.5 yields:
The differences are:
"ngInject;"
is repeatedFor our use case, the repetition is probably not a real problem, however the re-ordering is. If any of these two are by design now, we can work around - but I wanted to double check with the TypeScript developers because it seems to be a bit unexpected.
🕗 Version & Regression Information
We observed errors in a AngularJS-based project using
ng-annotate-patched
which relies on the string to annotate classes for AngularJS. It works wiht TS 4.5 and broke with TS 4.6.TS 4.6.2 (broken)
TS 4.5.5 (good)
⏯ Playground Link
https://www.typescriptlang.org/play?removeComments=true&target=2&ts=4.5.5#code/MYGwhgzhAECiAeYC2AHEBTaBvAUASGAHsA7CAFwCcBXYMwigChQoEsA3MMzAQQC5pyrYgHMAlNnx4ARCICSxAFbpaUgNz4Avji1A
The text was updated successfully, but these errors were encountered: