Skip to content

Commit 3500c92

Browse files
authored
feat(56600): JSDoc @callback doesn't support this parameters via @this (microsoft#56610)
1 parent 99d2435 commit 3500c92

File tree

5 files changed

+80
-8
lines changed

5 files changed

+80
-8
lines changed

src/compiler/checker.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,7 @@ import {
597597
isJSDocSatisfiesTag,
598598
isJSDocSignature,
599599
isJSDocTemplateTag,
600+
isJSDocThisTag,
600601
isJSDocTypeAlias,
601602
isJSDocTypeAssertion,
602603
isJSDocTypedefTag,
@@ -15079,6 +15080,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1507915080
let flags = SignatureFlags.None;
1508015081
let minArgumentCount = 0;
1508115082
let thisParameter: Symbol | undefined;
15083+
let thisTag: JSDocThisTag | undefined = isInJSFile(declaration) ? getJSDocThisTag(declaration) : undefined;
1508215084
let hasThisParameter = false;
1508315085
const iife = getImmediatelyInvokedFunctionExpression(declaration);
1508415086
const isJSConstructSignature = isJSDocConstructSignature(declaration);
@@ -15096,6 +15098,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1509615098
// signature.
1509715099
for (let i = isJSConstructSignature ? 1 : 0; i < declaration.parameters.length; i++) {
1509815100
const param = declaration.parameters[i];
15101+
if (isInJSFile(param) && isJSDocThisTag(param)) {
15102+
thisTag = param;
15103+
continue;
15104+
}
1509915105

1510015106
let paramSymbol = param.symbol;
1510115107
const type = isJSDocParameterTag(param) ? (param.typeExpression && param.typeExpression.type) : param.type;
@@ -15139,11 +15145,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1513915145
}
1514015146
}
1514115147

15142-
if (isInJSFile(declaration)) {
15143-
const thisTag = getJSDocThisTag(declaration);
15144-
if (thisTag && thisTag.typeExpression) {
15145-
thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression));
15146-
}
15148+
if (thisTag && thisTag.typeExpression) {
15149+
thisParameter = createSymbolWithType(createSymbol(SymbolFlags.FunctionScopedVariable, InternalSymbolName.This), getTypeFromTypeNode(thisTag.typeExpression));
1514715150
}
1514815151

1514915152
const hostDeclaration = isJSDocSignature(declaration) ? getEffectiveJSDocHost(declaration) : declaration;

src/compiler/parser.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -9343,7 +9343,7 @@ namespace Parser {
93439343
function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) {
93449344
if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
93459345
const pos = getNodePos();
9346-
let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | false;
9346+
let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | JSDocThisTag | false;
93479347
let children: JSDocPropertyLikeTag[] | undefined;
93489348
while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) {
93499349
if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
@@ -9635,7 +9635,7 @@ namespace Parser {
96359635
return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false;
96369636
}
96379637

9638-
function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false {
9638+
function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false {
96399639
let canParseTag = true;
96409640
let seenAsterisk = false;
96419641
while (true) {
@@ -9672,7 +9672,7 @@ namespace Parser {
96729672
}
96739673
}
96749674

9675-
function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | false {
9675+
function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false {
96769676
Debug.assert(token() === SyntaxKind.AtToken);
96779677
const start = scanner.getTokenFullStart();
96789678
nextTokenJSDoc();
@@ -9694,6 +9694,8 @@ namespace Parser {
96949694
break;
96959695
case "template":
96969696
return parseTemplateTag(start, tagName, indent, indentText);
9697+
case "this":
9698+
return parseThisTag(start, tagName, indent, indentText);
96979699
default:
96989700
return false;
96999701
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//// [tests/cases/conformance/jsdoc/callbackTag4.ts] ////
2+
3+
=== ./a.js ===
4+
/**
5+
* @callback C
6+
* @this {{ a: string, b: number }}
7+
* @param {string} a
8+
* @param {number} b
9+
* @returns {boolean}
10+
*/
11+
12+
/** @type {C} */
13+
const cb = function (a, b) {
14+
>cb : Symbol(cb, Decl(a.js, 9, 5))
15+
>a : Symbol(a, Decl(a.js, 9, 21))
16+
>b : Symbol(b, Decl(a.js, 9, 23))
17+
18+
this
19+
>this : Symbol(this)
20+
21+
return true
22+
}
23+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//// [tests/cases/conformance/jsdoc/callbackTag4.ts] ////
2+
3+
=== ./a.js ===
4+
/**
5+
* @callback C
6+
* @this {{ a: string, b: number }}
7+
* @param {string} a
8+
* @param {number} b
9+
* @returns {boolean}
10+
*/
11+
12+
/** @type {C} */
13+
const cb = function (a, b) {
14+
>cb : C
15+
>function (a, b) { this return true} : (this: { a: string; b: number; }, a: string, b: number) => boolean
16+
>a : string
17+
>b : number
18+
19+
this
20+
>this : { a: string; b: number; }
21+
22+
return true
23+
>true : true
24+
}
25+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// @allowJs: true
2+
// @checkJs: true
3+
// @strict: true
4+
// @noEmit: true
5+
// @filename: ./a.js
6+
7+
/**
8+
* @callback C
9+
* @this {{ a: string, b: number }}
10+
* @param {string} a
11+
* @param {number} b
12+
* @returns {boolean}
13+
*/
14+
15+
/** @type {C} */
16+
const cb = function (a, b) {
17+
this
18+
return true
19+
}

0 commit comments

Comments
 (0)