From 17e4989d84f3ac05c75373de6c5d8c2fea275d5b Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 10 Jan 2024 21:54:52 +0000 Subject: [PATCH 1/5] Add test for a `nonnull` tag. --- .../conformance/jsdoc/jsdocNonNullTag.ts | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 tests/cases/conformance/jsdoc/jsdocNonNullTag.ts diff --git a/tests/cases/conformance/jsdoc/jsdocNonNullTag.ts b/tests/cases/conformance/jsdoc/jsdocNonNullTag.ts new file mode 100644 index 0000000000000..8b01512ca15ea --- /dev/null +++ b/tests/cases/conformance/jsdoc/jsdocNonNullTag.ts @@ -0,0 +1,115 @@ +// @checkJs: true +// @target: esnext +// @suppressOutputPathCheck: true +// @strict: true + + +// @filename: file1.js +/** @type {(x: string | null | undefined) => string} */ +export function fn1(x) { + const nonNulledX = /** @nonnull */ (x); + return nonNulledX.toUpperCase(); +} + + +// @filename: file2.js +/** @type {(x: string | null | undefined) => string} */ +export function fn2(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +// @filename: file3.js +/** @type {(x: string | null) => string} */ +export function fn3(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +// @filename: file4.js +/** @type {(x: string | undefined) => string} */ +export function fn4(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +// @filename: file5.js +/** + * @nonnull + * @type {string} + */ +export const var5; + +const p5 = Promise.resolve(true); + +p5.then(() => { + var5 = "hello!"; +}); +p5.then(() => { + return var5.toUpperCase(); +}); + + +// @filename: file6.js +/** + * @nonnull + * @type {string | undefined} + */ +export const var6; + +const p6 = Promise.resolve(true); + +p6.then(() => { + var6 = "hello!"; +}); +p6.then(() => { + return var5.toUpperCase(); +}); + + +// @filename: file7.js +/** + * @nonnull + * @type {string | undefined} + */ +export class Class7 { + /** + * @nonnull + * @type {string} + */ + abc; + + /** + * @param {string} abc + */ + constructor(abc) { + this.abc = abc; + } +} + + +// @filename: file8.js +/** + * @nonnull + * @type {string | undefined} + */ +export class Class8 { + /** + * @param {string} abc + */ + constructor(abc) { + /** @private */ + this.abc = abc; + } +} + + +// @filename: file9.js +/** @type {() => string | null} */ +export const tryGetString9 = () => { + throw "Not implemented!"; +} + +/** @nonull */ +export const someString9 = tryGetString9(); + From 6a1d274eb01e74cc2b64bfb4d19881816642049d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 10 Jan 2024 21:55:01 +0000 Subject: [PATCH 2/5] Accept baselines. --- .../reference/jsdocNonNullTag.errors.txt | 139 +++++++++++ tests/baselines/reference/jsdocNonNullTag.js | 199 +++++++++++++++ .../reference/jsdocNonNullTag.symbols | 194 +++++++++++++++ .../baselines/reference/jsdocNonNullTag.types | 232 ++++++++++++++++++ 4 files changed, 764 insertions(+) create mode 100644 tests/baselines/reference/jsdocNonNullTag.errors.txt create mode 100644 tests/baselines/reference/jsdocNonNullTag.js create mode 100644 tests/baselines/reference/jsdocNonNullTag.symbols create mode 100644 tests/baselines/reference/jsdocNonNullTag.types diff --git a/tests/baselines/reference/jsdocNonNullTag.errors.txt b/tests/baselines/reference/jsdocNonNullTag.errors.txt new file mode 100644 index 0000000000000..f0cff254b9e11 --- /dev/null +++ b/tests/baselines/reference/jsdocNonNullTag.errors.txt @@ -0,0 +1,139 @@ +file1.js(4,12): error TS18049: 'nonNulledX' is possibly 'null' or 'undefined'. +file2.js(3,12): error TS2533: Object is possibly 'null' or 'undefined'. +file3.js(3,12): error TS2531: Object is possibly 'null'. +file4.js(3,12): error TS2532: Object is possibly 'undefined'. +file5.js(5,14): error TS1155: 'const' declarations must be initialized. +file5.js(10,5): error TS2588: Cannot assign to 'var5' because it is a constant. +file6.js(5,14): error TS1155: 'const' declarations must be initialized. +file6.js(10,5): error TS2588: Cannot assign to 'var6' because it is a constant. +file6.js(13,12): error TS2304: Cannot find name 'var5'. + + +==== file1.js (1 errors) ==== + /** @type {(x: string | null | undefined) => string} */ + export function fn1(x) { + const nonNulledX = /** @nonnull */ (x); + return nonNulledX.toUpperCase(); + ~~~~~~~~~~ +!!! error TS18049: 'nonNulledX' is possibly 'null' or 'undefined'. + } + + +==== file2.js (1 errors) ==== + /** @type {(x: string | null | undefined) => string} */ + export function fn2(x) { + return (/** @nonnull */ (x)).toUpperCase(); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2533: Object is possibly 'null' or 'undefined'. + } + + +==== file3.js (1 errors) ==== + /** @type {(x: string | null) => string} */ + export function fn3(x) { + return (/** @nonnull */ (x)).toUpperCase(); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2531: Object is possibly 'null'. + } + + +==== file4.js (1 errors) ==== + /** @type {(x: string | undefined) => string} */ + export function fn4(x) { + return (/** @nonnull */ (x)).toUpperCase(); + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + } + + +==== file5.js (2 errors) ==== + /** + * @nonnull + * @type {string} + */ + export const var5; + ~~~~ +!!! error TS1155: 'const' declarations must be initialized. + + const p5 = Promise.resolve(true); + + p5.then(() => { + var5 = "hello!"; + ~~~~ +!!! error TS2588: Cannot assign to 'var5' because it is a constant. + }); + p5.then(() => { + return var5.toUpperCase(); + }); + + +==== file6.js (3 errors) ==== + /** + * @nonnull + * @type {string | undefined} + */ + export const var6; + ~~~~ +!!! error TS1155: 'const' declarations must be initialized. + + const p6 = Promise.resolve(true); + + p6.then(() => { + var6 = "hello!"; + ~~~~ +!!! error TS2588: Cannot assign to 'var6' because it is a constant. + }); + p6.then(() => { + return var5.toUpperCase(); + ~~~~ +!!! error TS2304: Cannot find name 'var5'. + }); + + +==== file7.js (0 errors) ==== + /** + * @nonnull + * @type {string | undefined} + */ + export class Class7 { + /** + * @nonnull + * @type {string} + */ + abc; + + /** + * @param {string} abc + */ + constructor(abc) { + this.abc = abc; + } + } + + +==== file8.js (0 errors) ==== + /** + * @nonnull + * @type {string | undefined} + */ + export class Class8 { + /** + * @param {string} abc + */ + constructor(abc) { + /** @private */ + this.abc = abc; + } + } + + +==== file9.js (0 errors) ==== + /** @type {() => string | null} */ + export const tryGetString9 = () => { + throw "Not implemented!"; + } + + /** @nonull */ + export const someString9 = tryGetString9(); + + \ No newline at end of file diff --git a/tests/baselines/reference/jsdocNonNullTag.js b/tests/baselines/reference/jsdocNonNullTag.js new file mode 100644 index 0000000000000..4f987f12095e3 --- /dev/null +++ b/tests/baselines/reference/jsdocNonNullTag.js @@ -0,0 +1,199 @@ +//// [tests/cases/conformance/jsdoc/jsdocNonNullTag.ts] //// + +//// [file1.js] +/** @type {(x: string | null | undefined) => string} */ +export function fn1(x) { + const nonNulledX = /** @nonnull */ (x); + return nonNulledX.toUpperCase(); +} + + +//// [file2.js] +/** @type {(x: string | null | undefined) => string} */ +export function fn2(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +//// [file3.js] +/** @type {(x: string | null) => string} */ +export function fn3(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +//// [file4.js] +/** @type {(x: string | undefined) => string} */ +export function fn4(x) { + return (/** @nonnull */ (x)).toUpperCase(); +} + + +//// [file5.js] +/** + * @nonnull + * @type {string} + */ +export const var5; + +const p5 = Promise.resolve(true); + +p5.then(() => { + var5 = "hello!"; +}); +p5.then(() => { + return var5.toUpperCase(); +}); + + +//// [file6.js] +/** + * @nonnull + * @type {string | undefined} + */ +export const var6; + +const p6 = Promise.resolve(true); + +p6.then(() => { + var6 = "hello!"; +}); +p6.then(() => { + return var5.toUpperCase(); +}); + + +//// [file7.js] +/** + * @nonnull + * @type {string | undefined} + */ +export class Class7 { + /** + * @nonnull + * @type {string} + */ + abc; + + /** + * @param {string} abc + */ + constructor(abc) { + this.abc = abc; + } +} + + +//// [file8.js] +/** + * @nonnull + * @type {string | undefined} + */ +export class Class8 { + /** + * @param {string} abc + */ + constructor(abc) { + /** @private */ + this.abc = abc; + } +} + + +//// [file9.js] +/** @type {() => string | null} */ +export const tryGetString9 = () => { + throw "Not implemented!"; +} + +/** @nonull */ +export const someString9 = tryGetString9(); + + + +//// [file1.js] +/** @type {(x: string | null | undefined) => string} */ +export function fn1(x) { + const nonNulledX = /** @nonnull */ (x); + return nonNulledX.toUpperCase(); +} +//// [file2.js] +/** @type {(x: string | null | undefined) => string} */ +export function fn2(x) { + return ( /** @nonnull */(x)).toUpperCase(); +} +//// [file3.js] +/** @type {(x: string | null) => string} */ +export function fn3(x) { + return ( /** @nonnull */(x)).toUpperCase(); +} +//// [file4.js] +/** @type {(x: string | undefined) => string} */ +export function fn4(x) { + return ( /** @nonnull */(x)).toUpperCase(); +} +//// [file5.js] +/** + * @nonnull + * @type {string} + */ +export const var5; +const p5 = Promise.resolve(true); +p5.then(() => { + var5 = "hello!"; +}); +p5.then(() => { + return var5.toUpperCase(); +}); +//// [file6.js] +/** + * @nonnull + * @type {string | undefined} + */ +export const var6; +const p6 = Promise.resolve(true); +p6.then(() => { + var6 = "hello!"; +}); +p6.then(() => { + return var5.toUpperCase(); +}); +//// [file7.js] +/** + * @nonnull + * @type {string | undefined} + */ +export class Class7 { + /** + * @nonnull + * @type {string} + */ + abc; + /** + * @param {string} abc + */ + constructor(abc) { + this.abc = abc; + } +} +//// [file8.js] +/** + * @nonnull + * @type {string | undefined} + */ +export class Class8 { + /** + * @param {string} abc + */ + constructor(abc) { + /** @private */ + this.abc = abc; + } +} +//// [file9.js] +/** @type {() => string | null} */ +export const tryGetString9 = () => { + throw "Not implemented!"; +}; +/** @nonull */ +export const someString9 = tryGetString9(); diff --git a/tests/baselines/reference/jsdocNonNullTag.symbols b/tests/baselines/reference/jsdocNonNullTag.symbols new file mode 100644 index 0000000000000..6c21d0cca06e4 --- /dev/null +++ b/tests/baselines/reference/jsdocNonNullTag.symbols @@ -0,0 +1,194 @@ +//// [tests/cases/conformance/jsdoc/jsdocNonNullTag.ts] //// + +=== file1.js === +/** @type {(x: string | null | undefined) => string} */ +export function fn1(x) { +>fn1 : Symbol(fn1, Decl(file1.js, 0, 0)) +>x : Symbol(x, Decl(file1.js, 1, 20)) + + const nonNulledX = /** @nonnull */ (x); +>nonNulledX : Symbol(nonNulledX, Decl(file1.js, 2, 9)) +>x : Symbol(x, Decl(file1.js, 1, 20)) + + return nonNulledX.toUpperCase(); +>nonNulledX.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>nonNulledX : Symbol(nonNulledX, Decl(file1.js, 2, 9)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +} + + +=== file2.js === +/** @type {(x: string | null | undefined) => string} */ +export function fn2(x) { +>fn2 : Symbol(fn2, Decl(file2.js, 0, 0)) +>x : Symbol(x, Decl(file2.js, 1, 20)) + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(file2.js, 1, 20)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +} + + +=== file3.js === +/** @type {(x: string | null) => string} */ +export function fn3(x) { +>fn3 : Symbol(fn3, Decl(file3.js, 0, 0)) +>x : Symbol(x, Decl(file3.js, 1, 20)) + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(file3.js, 1, 20)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +} + + +=== file4.js === +/** @type {(x: string | undefined) => string} */ +export function fn4(x) { +>fn4 : Symbol(fn4, Decl(file4.js, 0, 0)) +>x : Symbol(x, Decl(file4.js, 1, 20)) + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>x : Symbol(x, Decl(file4.js, 1, 20)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +} + + +=== file5.js === +/** + * @nonnull + * @type {string} + */ +export const var5; +>var5 : Symbol(var5, Decl(file5.js, 4, 12)) + +const p5 = Promise.resolve(true); +>p5 : Symbol(p5, Decl(file5.js, 6, 5)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +p5.then(() => { +>p5.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>p5 : Symbol(p5, Decl(file5.js, 6, 5)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) + + var5 = "hello!"; +>var5 : Symbol(var5, Decl(file5.js, 4, 12)) + +}); +p5.then(() => { +>p5.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>p5 : Symbol(p5, Decl(file5.js, 6, 5)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) + + return var5.toUpperCase(); +>var5.toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) +>var5 : Symbol(var5, Decl(file5.js, 4, 12)) +>toUpperCase : Symbol(String.toUpperCase, Decl(lib.es5.d.ts, --, --)) + +}); + + +=== file6.js === +/** + * @nonnull + * @type {string | undefined} + */ +export const var6; +>var6 : Symbol(var6, Decl(file6.js, 4, 12)) + +const p6 = Promise.resolve(true); +>p6 : Symbol(p6, Decl(file6.js, 6, 5)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + +p6.then(() => { +>p6.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>p6 : Symbol(p6, Decl(file6.js, 6, 5)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) + + var6 = "hello!"; +>var6 : Symbol(var6, Decl(file6.js, 4, 12)) + +}); +p6.then(() => { +>p6.then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) +>p6 : Symbol(p6, Decl(file6.js, 6, 5)) +>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --)) + + return var5.toUpperCase(); +}); + + +=== file7.js === +/** + * @nonnull + * @type {string | undefined} + */ +export class Class7 { +>Class7 : Symbol(Class7, Decl(file7.js, 0, 0)) + + /** + * @nonnull + * @type {string} + */ + abc; +>abc : Symbol(Class7.abc, Decl(file7.js, 4, 21)) + + /** + * @param {string} abc + */ + constructor(abc) { +>abc : Symbol(abc, Decl(file7.js, 14, 16)) + + this.abc = abc; +>this.abc : Symbol(Class7.abc, Decl(file7.js, 4, 21)) +>this : Symbol(Class7, Decl(file7.js, 0, 0)) +>abc : Symbol(Class7.abc, Decl(file7.js, 4, 21)) +>abc : Symbol(abc, Decl(file7.js, 14, 16)) + } +} + + +=== file8.js === +/** + * @nonnull + * @type {string | undefined} + */ +export class Class8 { +>Class8 : Symbol(Class8, Decl(file8.js, 0, 0)) + + /** + * @param {string} abc + */ + constructor(abc) { +>abc : Symbol(abc, Decl(file8.js, 8, 16)) + + /** @private */ + this.abc = abc; +>this.abc : Symbol(Class8.abc, Decl(file8.js, 8, 22)) +>this : Symbol(Class8, Decl(file8.js, 0, 0)) +>abc : Symbol(Class8.abc, Decl(file8.js, 8, 22)) +>abc : Symbol(abc, Decl(file8.js, 8, 16)) + } +} + + +=== file9.js === +/** @type {() => string | null} */ +export const tryGetString9 = () => { +>tryGetString9 : Symbol(tryGetString9, Decl(file9.js, 1, 12)) + + throw "Not implemented!"; +} + +/** @nonull */ +export const someString9 = tryGetString9(); +>someString9 : Symbol(someString9, Decl(file9.js, 6, 12)) +>tryGetString9 : Symbol(tryGetString9, Decl(file9.js, 1, 12)) + + diff --git a/tests/baselines/reference/jsdocNonNullTag.types b/tests/baselines/reference/jsdocNonNullTag.types new file mode 100644 index 0000000000000..43c130ec96d63 --- /dev/null +++ b/tests/baselines/reference/jsdocNonNullTag.types @@ -0,0 +1,232 @@ +//// [tests/cases/conformance/jsdoc/jsdocNonNullTag.ts] //// + +=== file1.js === +/** @type {(x: string | null | undefined) => string} */ +export function fn1(x) { +>fn1 : (x: string | null | undefined) => string +>x : string | null | undefined + + const nonNulledX = /** @nonnull */ (x); +>nonNulledX : string | null | undefined +>(x) : string | null | undefined +>x : string | null | undefined + + return nonNulledX.toUpperCase(); +>nonNulledX.toUpperCase() : string +>nonNulledX.toUpperCase : () => string +>nonNulledX : string | null | undefined +>toUpperCase : () => string +} + + +=== file2.js === +/** @type {(x: string | null | undefined) => string} */ +export function fn2(x) { +>fn2 : (x: string | null | undefined) => string +>x : string | null | undefined + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase() : string +>(/** @nonnull */ (x)).toUpperCase : () => string +>(/** @nonnull */ (x)) : string | null | undefined +>(x) : string | null | undefined +>x : string | null | undefined +>toUpperCase : () => string +} + + +=== file3.js === +/** @type {(x: string | null) => string} */ +export function fn3(x) { +>fn3 : (x: string | null) => string +>x : string | null + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase() : string +>(/** @nonnull */ (x)).toUpperCase : () => string +>(/** @nonnull */ (x)) : string | null +>(x) : string | null +>x : string | null +>toUpperCase : () => string +} + + +=== file4.js === +/** @type {(x: string | undefined) => string} */ +export function fn4(x) { +>fn4 : (x: string | undefined) => string +>x : string | undefined + + return (/** @nonnull */ (x)).toUpperCase(); +>(/** @nonnull */ (x)).toUpperCase() : string +>(/** @nonnull */ (x)).toUpperCase : () => string +>(/** @nonnull */ (x)) : string | undefined +>(x) : string | undefined +>x : string | undefined +>toUpperCase : () => string +} + + +=== file5.js === +/** + * @nonnull + * @type {string} + */ +export const var5; +>var5 : string + +const p5 = Promise.resolve(true); +>p5 : Promise +>Promise.resolve(true) : Promise +>Promise.resolve : { (): Promise; (value: T): Promise>; (value: T_1 | PromiseLike): Promise>; } +>Promise : PromiseConstructor +>resolve : { (): Promise; (value: T): Promise>; (value: T_1 | PromiseLike): Promise>; } +>true : true + +p5.then(() => { +>p5.then(() => { var5 = "hello!";}) : Promise +>p5.then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>p5 : Promise +>then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>() => { var5 = "hello!";} : () => void + + var5 = "hello!"; +>var5 = "hello!" : "hello!" +>var5 : any +>"hello!" : "hello!" + +}); +p5.then(() => { +>p5.then(() => { return var5.toUpperCase();}) : Promise +>p5.then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>p5 : Promise +>then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>() => { return var5.toUpperCase();} : () => string + + return var5.toUpperCase(); +>var5.toUpperCase() : string +>var5.toUpperCase : () => string +>var5 : string +>toUpperCase : () => string + +}); + + +=== file6.js === +/** + * @nonnull + * @type {string | undefined} + */ +export const var6; +>var6 : string | undefined + +const p6 = Promise.resolve(true); +>p6 : Promise +>Promise.resolve(true) : Promise +>Promise.resolve : { (): Promise; (value: T): Promise>; (value: T_1 | PromiseLike): Promise>; } +>Promise : PromiseConstructor +>resolve : { (): Promise; (value: T): Promise>; (value: T_1 | PromiseLike): Promise>; } +>true : true + +p6.then(() => { +>p6.then(() => { var6 = "hello!";}) : Promise +>p6.then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>p6 : Promise +>then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>() => { var6 = "hello!";} : () => void + + var6 = "hello!"; +>var6 = "hello!" : "hello!" +>var6 : any +>"hello!" : "hello!" + +}); +p6.then(() => { +>p6.then(() => { return var5.toUpperCase();}) : Promise +>p6.then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>p6 : Promise +>then : (onfulfilled?: ((value: boolean) => TResult1 | PromiseLike) | null | undefined, onrejected?: ((reason: any) => TResult2 | PromiseLike) | null | undefined) => Promise +>() => { return var5.toUpperCase();} : () => any + + return var5.toUpperCase(); +>var5.toUpperCase() : any +>var5.toUpperCase : any +>var5 : any +>toUpperCase : any + +}); + + +=== file7.js === +/** + * @nonnull + * @type {string | undefined} + */ +export class Class7 { +>Class7 : Class7 + + /** + * @nonnull + * @type {string} + */ + abc; +>abc : string + + /** + * @param {string} abc + */ + constructor(abc) { +>abc : string + + this.abc = abc; +>this.abc = abc : string +>this.abc : string +>this : this +>abc : string +>abc : string + } +} + + +=== file8.js === +/** + * @nonnull + * @type {string | undefined} + */ +export class Class8 { +>Class8 : Class8 + + /** + * @param {string} abc + */ + constructor(abc) { +>abc : string + + /** @private */ + this.abc = abc; +>this.abc = abc : string +>this.abc : any +>this : this +>abc : any +>abc : string + } +} + + +=== file9.js === +/** @type {() => string | null} */ +export const tryGetString9 = () => { +>tryGetString9 : () => string | null +>() => { throw "Not implemented!";} : () => string | null + + throw "Not implemented!"; +>"Not implemented!" : "Not implemented!" +} + +/** @nonull */ +export const someString9 = tryGetString9(); +>someString9 : string | null +>tryGetString9() : string | null +>tryGetString9 : () => string | null + + From b715edf44c5286bcfde04ad5257b0d08f7c4a6a5 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 10 Jan 2024 21:58:01 +0000 Subject: [PATCH 3/5] Implement a `nonnull` JSDoc tag. --- src/compiler/checker.ts | 4 ++++ src/compiler/emitter.ts | 1 + src/compiler/factory/nodeFactory.ts | 7 +++++++ src/compiler/factory/nodeTests.ts | 5 +++++ src/compiler/parser.ts | 7 ++++++- src/compiler/types.ts | 22 ++++++++++++++++++++-- src/compiler/utilities.ts | 7 +++++++ src/compiler/utilitiesPublic.ts | 7 +++++++ src/services/jsDoc.ts | 1 + 9 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 508f6bb323706..947843e668198 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -587,6 +587,7 @@ import { isJSDocNameReference, isJSDocNode, isJSDocNonNullableType, + isJSDocNonNullExpression, isJSDocNullableType, isJSDocOptionalParameter, isJSDocOptionalType, @@ -39397,6 +39398,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isJSDocTypeAssertion(node)) { return checkAssertionWorker(node, checkMode); } + if (isJSDocNonNullExpression(node)) { + return getNonNullableType(checkExpression(node.expression)); + } } return checkExpression(node.expression, checkMode); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 3afb23c6df378..4212712b86da0 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2170,6 +2170,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri case SyntaxKind.JSDocTag: case SyntaxKind.JSDocClassTag: case SyntaxKind.JSDocOverrideTag: + case SyntaxKind.JSDocNonNullTag: return emitJSDocSimpleTag(node as JSDocTag); case SyntaxKind.JSDocAugmentsTag: case SyntaxKind.JSDocImplementsTag: diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 907ab3833b672..42194598cb30b 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -246,6 +246,7 @@ import { JSDocNameReference, JSDocNamespaceDeclaration, JSDocNonNullableType, + JSDocNonNullTag, JSDocNullableType, JSDocOptionalType, JSDocOverloadTag, @@ -965,6 +966,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode get updateJSDocThrowsTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocThrowsTag); }, + get createJSDocNonNullTag() { + return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocNonNullTag); + }, + get updateJSDocNonNullTag() { + return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocNonNullTag); + }, get createJSDocSatisfiesTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocSatisfiesTag); }, diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index eca54d346d882..76b91e7b89710 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -98,6 +98,7 @@ import { JSDocNamepathType, JSDocNameReference, JSDocNonNullableType, + JSDocNonNullTag, JSDocNullableType, JSDocOptionalType, JSDocOverloadTag, @@ -1138,6 +1139,10 @@ export function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag { return node.kind === SyntaxKind.JSDocReadonlyTag; } +export function isJSDocNonNullTag(node: Node): node is JSDocNonNullTag { + return node.kind === SyntaxKind.JSDocNonNullTag; +} + export function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag { return node.kind === SyntaxKind.JSDocOverrideTag; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 2f411c435492a..7ab791b716d70 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -182,6 +182,7 @@ import { JSDocNameReference, JSDocNamespaceDeclaration, JSDocNonNullableType, + JSDocNonNullTag, JSDocNullableType, JSDocOptionalType, JSDocOverloadTag, @@ -1125,6 +1126,7 @@ const forEachChildTable: ForEachChildTable = { [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocNonNullTag]: forEachChildInJSDocTag, [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, }; @@ -1209,7 +1211,7 @@ function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | return visitNode(cbNode, node.name); } -function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { +function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag | JSDocNonNullTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.tagName) || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); } @@ -9066,6 +9068,9 @@ namespace Parser { case "satisfies": tag = parseSatisfiesTag(start, tagName, margin, indentText); break; + case "nonnull": + tag = parseSimpleTag(start, factory.createJSDocNonNullTag, tagName, margin, indentText); + break; case "see": tag = parseSeeTag(start, tagName, margin, indentText); break; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 23873de4824a8..b886869a48935 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -447,6 +447,7 @@ export const enum SyntaxKind { JSDocPropertyTag, JSDocThrowsTag, JSDocSatisfiesTag, + JSDocNonNullTag, // Synthesized list SyntaxList, @@ -489,9 +490,9 @@ export const enum SyntaxKind { LastStatement = DebuggerStatement, FirstNode = QualifiedName, FirstJSDocNode = JSDocTypeExpression, - LastJSDocNode = JSDocSatisfiesTag, + LastJSDocNode = JSDocNonNullTag, FirstJSDocTagNode = JSDocTag, - LastJSDocTagNode = JSDocSatisfiesTag, + LastJSDocTagNode = JSDocNonNullTag, /** @internal */ FirstContextualKeyword = AbstractKeyword, /** @internal */ LastContextualKeyword = OfKeyword, } @@ -1044,6 +1045,7 @@ export type ForEachChildNodes = | JSDocThrowsTag | JSDocOverrideTag | JSDocSatisfiesTag + | JSDocNonNullTag | JSDocOverloadTag; /** @internal */ @@ -4060,11 +4062,25 @@ export interface JSDocSatisfiesTag extends JSDocTag { readonly typeExpression: JSDocTypeExpression; } +/** + * NOTE: this is different from {@link JSDocNonNullableType} + * which is its own kind of type node. This is a tag that acts + * like the `!` postfix operator in TypeScript. + **/ +export interface JSDocNonNullTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocNonNullTag; +} + /** @internal */ export interface JSDocSatisfiesExpression extends ParenthesizedExpression { readonly _jsDocSatisfiesExpressionBrand: never; } +/** @internal */ +export interface JSDocNonNullExpression extends ParenthesizedExpression { + readonly _jsDocNonNullExpressionBrand: never; +} + // NOTE: Ensure this is up-to-date with src/debug/debug.ts // dprint-ignore export const enum FlowFlags { @@ -8788,6 +8804,8 @@ export interface NodeFactory { updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray | undefined): JSDocThrowsTag; createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocSatisfiesTag; updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocSatisfiesTag; + createJSDocNonNullTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocNonNullTag; + updateJSDocNonNullTag(node: JSDocNonNullTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocNonNullTag; createJSDocText(text: string): JSDocText; updateJSDocText(node: JSDocText, text: string): JSDocText; createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 36fb67860a32b..db166121e3588 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -169,6 +169,7 @@ import { getJSDocAugmentsTag, getJSDocDeprecatedTagNoCache, getJSDocImplementsTags, + getJSDocNonNullTag, getJSDocOverrideTagNoCache, getJSDocParameterTags, getJSDocParameterTagsNoCache, @@ -356,6 +357,7 @@ import { JSDocCallbackTag, JSDocEnumTag, JSDocMemberName, + JSDocNonNullExpression, JSDocOverloadTag, JSDocParameterTag, JSDocPropertyLikeTag, @@ -10579,6 +10581,11 @@ export function tryGetJSDocSatisfiesTypeNode(node: Node) { return tag && tag.typeExpression && tag.typeExpression.type; } +/** @internal */ +export function isJSDocNonNullExpression(node: Node): node is JSDocNonNullExpression { + return isInJSFile(node) && isParenthesizedExpression(node) && hasJSDocNodes(node) && !!getJSDocNonNullTag(node); +} + /** @internal */ export function getEscapedTextOfJsxAttributeName(node: JsxAttributeName): __String { return isIdentifier(node) ? node.escapedText : getEscapedTextOfJsxNamespacedName(node); diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 688ef16272039..b384e4cfb9dcd 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -133,6 +133,7 @@ import { isJSDocEnumTag, isJSDocFunctionType, isJSDocImplementsTag, + isJSDocNonNullTag, isJSDocOverloadTag, isJSDocOverrideTag, isJSDocParameterTag, @@ -182,6 +183,7 @@ import { JSDocLinkCode, JSDocLinkPlain, JSDocNamespaceBody, + JSDocNonNullTag, JSDocOverrideTag, JSDocParameterTag, JSDocPrivateTag, @@ -1093,6 +1095,11 @@ export function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined { return getFirstJSDocTag(node, isJSDocReadonlyTag); } +/** Gets the JSDoc `nonnull` tag for the node if present */ +export function getJSDocNonNullTag(node: Node): JSDocNonNullTag | undefined { + return getFirstJSDocTag(node, isJSDocNonNullTag); +} + /** @internal */ export function getJSDocReadonlyTagNoCache(node: Node): JSDocReadonlyTag | undefined { return getFirstJSDocTag(node, isJSDocReadonlyTag, /*noCache*/ true); diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 6f387271048dc..396ed6429697b 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -149,6 +149,7 @@ const jsDocTagNames = [ "module", "name", "namespace", + "nonnull", "overload", "override", "package", From 5d2f33648326d0b1963c8425c0a6ac2905cf8c82 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 10 Jan 2024 21:59:04 +0000 Subject: [PATCH 4/5] Accepted baselines. --- tests/baselines/reference/api/typescript.d.ts | 30 ++- .../reference/jsdocNonNullTag.errors.txt | 20 +- .../baselines/reference/jsdocNonNullTag.types | 18 +- ...docParameterTagSnippetCompletion1.baseline | 238 ++++++++++++++++++ ...docParameterTagSnippetCompletion2.baseline | 70 ++++++ ...docParameterTagSnippetCompletion3.baseline | 84 +++++++ 6 files changed, 427 insertions(+), 33 deletions(-) diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index fe1a414ef6f51..074c4e1084a89 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4534,12 +4534,13 @@ declare namespace ts { JSDocPropertyTag = 355, JSDocThrowsTag = 356, JSDocSatisfiesTag = 357, - SyntaxList = 358, - NotEmittedStatement = 359, - PartiallyEmittedExpression = 360, - CommaListExpression = 361, - SyntheticReferenceExpression = 362, - Count = 363, + JSDocNonNullTag = 358, + SyntaxList = 359, + NotEmittedStatement = 360, + PartiallyEmittedExpression = 361, + CommaListExpression = 362, + SyntheticReferenceExpression = 363, + Count = 364, FirstAssignment = 64, LastAssignment = 79, FirstCompoundAssignment = 65, @@ -4568,9 +4569,9 @@ declare namespace ts { LastStatement = 259, FirstNode = 166, FirstJSDocNode = 316, - LastJSDocNode = 357, + LastJSDocNode = 358, FirstJSDocTagNode = 334, - LastJSDocTagNode = 357, + LastJSDocTagNode = 358, } type TriviaSyntaxKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia | SyntaxKind.NewLineTrivia | SyntaxKind.WhitespaceTrivia | SyntaxKind.ShebangTrivia | SyntaxKind.ConflictMarkerTrivia; type LiteralSyntaxKind = SyntaxKind.NumericLiteral | SyntaxKind.BigIntLiteral | SyntaxKind.StringLiteral | SyntaxKind.JsxText | SyntaxKind.JsxTextAllWhiteSpaces | SyntaxKind.RegularExpressionLiteral | SyntaxKind.NoSubstitutionTemplateLiteral; @@ -6376,6 +6377,14 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocSatisfiesTag; readonly typeExpression: JSDocTypeExpression; } + /** + * NOTE: this is different from {@link JSDocNonNullableType} + * which is its own kind of type node. This is a tag that acts + * like the `!` postfix operator in TypeScript. + */ + interface JSDocNonNullTag extends JSDocTag { + readonly kind: SyntaxKind.JSDocNonNullTag; + } enum FlowFlags { Unreachable = 1, Start = 2, @@ -8320,6 +8329,8 @@ declare namespace ts { updateJSDocThrowsTag(node: JSDocThrowsTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression | undefined, comment?: string | NodeArray | undefined): JSDocThrowsTag; createJSDocSatisfiesTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray): JSDocSatisfiesTag; updateJSDocSatisfiesTag(node: JSDocSatisfiesTag, tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined): JSDocSatisfiesTag; + createJSDocNonNullTag(tagName: Identifier | undefined, comment?: string | NodeArray): JSDocNonNullTag; + updateJSDocNonNullTag(node: JSDocNonNullTag, tagName: Identifier | undefined, comment?: string | NodeArray): JSDocNonNullTag; createJSDocText(text: string): JSDocText; updateJSDocText(node: JSDocText, text: string): JSDocText; createJSDocComment(comment?: string | NodeArray | undefined, tags?: readonly JSDocTag[] | undefined): JSDoc; @@ -9068,6 +9079,8 @@ declare namespace ts { function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc protected tag for the node if present */ function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined; + /** Gets the JSDoc `nonnull` tag for the node if present */ + function getJSDocNonNullTag(node: Node): JSDocNonNullTag | undefined; function getJSDocOverrideTagNoCache(node: Node): JSDocOverrideTag | undefined; /** Gets the JSDoc deprecated tag for the node if present */ function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined; @@ -9528,6 +9541,7 @@ declare namespace ts { function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag; function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag; function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag; + function isJSDocNonNullTag(node: Node): node is JSDocNonNullTag; function isJSDocOverrideTag(node: Node): node is JSDocOverrideTag; function isJSDocOverloadTag(node: Node): node is JSDocOverloadTag; function isJSDocDeprecatedTag(node: Node): node is JSDocDeprecatedTag; diff --git a/tests/baselines/reference/jsdocNonNullTag.errors.txt b/tests/baselines/reference/jsdocNonNullTag.errors.txt index f0cff254b9e11..0d095d7366b2d 100644 --- a/tests/baselines/reference/jsdocNonNullTag.errors.txt +++ b/tests/baselines/reference/jsdocNonNullTag.errors.txt @@ -1,7 +1,3 @@ -file1.js(4,12): error TS18049: 'nonNulledX' is possibly 'null' or 'undefined'. -file2.js(3,12): error TS2533: Object is possibly 'null' or 'undefined'. -file3.js(3,12): error TS2531: Object is possibly 'null'. -file4.js(3,12): error TS2532: Object is possibly 'undefined'. file5.js(5,14): error TS1155: 'const' declarations must be initialized. file5.js(10,5): error TS2588: Cannot assign to 'var5' because it is a constant. file6.js(5,14): error TS1155: 'const' declarations must be initialized. @@ -9,40 +5,32 @@ file6.js(10,5): error TS2588: Cannot assign to 'var6' because it is a constant. file6.js(13,12): error TS2304: Cannot find name 'var5'. -==== file1.js (1 errors) ==== +==== file1.js (0 errors) ==== /** @type {(x: string | null | undefined) => string} */ export function fn1(x) { const nonNulledX = /** @nonnull */ (x); return nonNulledX.toUpperCase(); - ~~~~~~~~~~ -!!! error TS18049: 'nonNulledX' is possibly 'null' or 'undefined'. } -==== file2.js (1 errors) ==== +==== file2.js (0 errors) ==== /** @type {(x: string | null | undefined) => string} */ export function fn2(x) { return (/** @nonnull */ (x)).toUpperCase(); - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2533: Object is possibly 'null' or 'undefined'. } -==== file3.js (1 errors) ==== +==== file3.js (0 errors) ==== /** @type {(x: string | null) => string} */ export function fn3(x) { return (/** @nonnull */ (x)).toUpperCase(); - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2531: Object is possibly 'null'. } -==== file4.js (1 errors) ==== +==== file4.js (0 errors) ==== /** @type {(x: string | undefined) => string} */ export function fn4(x) { return (/** @nonnull */ (x)).toUpperCase(); - ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2532: Object is possibly 'undefined'. } diff --git a/tests/baselines/reference/jsdocNonNullTag.types b/tests/baselines/reference/jsdocNonNullTag.types index 43c130ec96d63..63d468ab658df 100644 --- a/tests/baselines/reference/jsdocNonNullTag.types +++ b/tests/baselines/reference/jsdocNonNullTag.types @@ -7,14 +7,14 @@ export function fn1(x) { >x : string | null | undefined const nonNulledX = /** @nonnull */ (x); ->nonNulledX : string | null | undefined ->(x) : string | null | undefined +>nonNulledX : string +>(x) : string >x : string | null | undefined return nonNulledX.toUpperCase(); >nonNulledX.toUpperCase() : string >nonNulledX.toUpperCase : () => string ->nonNulledX : string | null | undefined +>nonNulledX : string >toUpperCase : () => string } @@ -28,8 +28,8 @@ export function fn2(x) { return (/** @nonnull */ (x)).toUpperCase(); >(/** @nonnull */ (x)).toUpperCase() : string >(/** @nonnull */ (x)).toUpperCase : () => string ->(/** @nonnull */ (x)) : string | null | undefined ->(x) : string | null | undefined +>(/** @nonnull */ (x)) : string +>(x) : string >x : string | null | undefined >toUpperCase : () => string } @@ -44,8 +44,8 @@ export function fn3(x) { return (/** @nonnull */ (x)).toUpperCase(); >(/** @nonnull */ (x)).toUpperCase() : string >(/** @nonnull */ (x)).toUpperCase : () => string ->(/** @nonnull */ (x)) : string | null ->(x) : string | null +>(/** @nonnull */ (x)) : string +>(x) : string >x : string | null >toUpperCase : () => string } @@ -60,8 +60,8 @@ export function fn4(x) { return (/** @nonnull */ (x)).toUpperCase(); >(/** @nonnull */ (x)).toUpperCase() : string >(/** @nonnull */ (x)).toUpperCase : () => string ->(/** @nonnull */ (x)) : string | undefined ->(x) : string | undefined +>(/** @nonnull */ (x)) : string +>(x) : string >x : string | undefined >toUpperCase : () => string } diff --git a/tests/baselines/reference/jsdocParameterTagSnippetCompletion1.baseline b/tests/baselines/reference/jsdocParameterTagSnippetCompletion1.baseline index 970b5ae25841e..763eb73840d8d 100644 --- a/tests/baselines/reference/jsdocParameterTagSnippetCompletion1.baseline +++ b/tests/baselines/reference/jsdocParameterTagSnippetCompletion1.baseline @@ -58,6 +58,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -154,6 +155,7 @@ // | @module // | @name // | @namespace +// | @nonnull // | @overload // | @override // | @package @@ -247,6 +249,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -345,6 +348,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -445,6 +449,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -540,6 +545,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -636,6 +642,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -732,6 +739,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -827,6 +835,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -923,6 +932,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1016,6 +1026,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1110,6 +1121,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1204,6 +1216,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1297,6 +1310,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1392,6 +1406,7 @@ // | @module // | @name // | @namespace +// | @nonnull // | @overload // | @override // | @package @@ -1485,6 +1500,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1580,6 +1596,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -2330,6 +2347,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -3449,6 +3479,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -4568,6 +4611,19 @@ ], "documentation": [] }, + { + "name": "@nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "@nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "@overload", "kind": "", @@ -5674,6 +5730,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -6780,6 +6849,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -7886,6 +7968,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -9005,6 +9100,19 @@ ], "documentation": [] }, + { + "name": "@nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "@nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "@overload", "kind": "", @@ -10111,6 +10219,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -11217,6 +11338,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -12323,6 +12457,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -13429,6 +13576,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -14535,6 +14695,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -15641,6 +15814,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -16747,6 +16933,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -17866,6 +18065,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -18972,6 +19184,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -20078,6 +20303,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", diff --git a/tests/baselines/reference/jsdocParameterTagSnippetCompletion2.baseline b/tests/baselines/reference/jsdocParameterTagSnippetCompletion2.baseline index 0e8cc9b8ceed1..bb26da978a572 100644 --- a/tests/baselines/reference/jsdocParameterTagSnippetCompletion2.baseline +++ b/tests/baselines/reference/jsdocParameterTagSnippetCompletion2.baseline @@ -58,6 +58,7 @@ // | @module // | @name // | @namespace +// | @nonnull // | @overload // | @override // | @package @@ -151,6 +152,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -249,6 +251,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -341,6 +344,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -434,6 +438,7 @@ // | @module // | @name // | @namespace +// | @nonnull // | @overload // | @override // | @package @@ -1182,6 +1187,19 @@ ], "documentation": [] }, + { + "name": "@nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "@nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "@overload", "kind": "", @@ -2290,6 +2308,19 @@ ], "documentation": [] }, + { + "name": "@nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "@nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "@overload", "kind": "", @@ -3398,6 +3429,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -4506,6 +4550,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -5614,6 +5671,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", diff --git a/tests/baselines/reference/jsdocParameterTagSnippetCompletion3.baseline b/tests/baselines/reference/jsdocParameterTagSnippetCompletion3.baseline index 31809167ab0f8..9c289d62e4161 100644 --- a/tests/baselines/reference/jsdocParameterTagSnippetCompletion3.baseline +++ b/tests/baselines/reference/jsdocParameterTagSnippetCompletion3.baseline @@ -58,6 +58,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -149,6 +150,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -241,6 +243,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -336,6 +339,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -431,6 +435,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -524,6 +529,7 @@ // | module // | name // | namespace +// | nonnull // | overload // | override // | package @@ -1273,6 +1279,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -2379,6 +2398,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -3485,6 +3517,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -4591,6 +4636,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -5697,6 +5755,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", @@ -6803,6 +6874,19 @@ ], "documentation": [] }, + { + "name": "nonnull", + "kind": "", + "kindModifiers": "", + "sortText": "11", + "displayParts": [ + { + "text": "nonnull", + "kind": "text" + } + ], + "documentation": [] + }, { "name": "overload", "kind": "", From 190cda48b813e6b7816d994c01cca0877a105de6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 12 Jan 2024 18:16:57 -0800 Subject: [PATCH 5/5] -* --- src/compiler/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index b886869a48935..7d243f97b5893 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -4066,7 +4066,7 @@ export interface JSDocSatisfiesTag extends JSDocTag { * NOTE: this is different from {@link JSDocNonNullableType} * which is its own kind of type node. This is a tag that acts * like the `!` postfix operator in TypeScript. - **/ + */ export interface JSDocNonNullTag extends JSDocTag { readonly kind: SyntaxKind.JSDocNonNullTag; }