Alias for module.exports.x = x (#40228)

* Alias for `module.exports.x = x`

This fixes #40155 in a surprisingly small amount of code.

* Treat any aliasable expression as an alias

* test internal references to exported class
This commit is contained in:
Nathan Shively-Sanders 2020-09-10 11:23:48 -07:00 committed by GitHub
parent 0636b9bfc1
commit e350c357d2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
47 changed files with 588 additions and 190 deletions

View file

@ -2806,10 +2806,10 @@ namespace ts {
return symbol;
});
if (symbol) {
const flags = isClassExpression(node.right) ?
SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.Class :
SymbolFlags.Property | SymbolFlags.ExportValue;
declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None);
const isAlias = isAliasableExpression(node.right) && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression));
const flags = isAlias ? SymbolFlags.Alias : SymbolFlags.Property | SymbolFlags.ExportValue;
const excludeFlags = isAlias ? SymbolFlags.AliasExcludes : SymbolFlags.None;
declareSymbol(symbol.exports!, symbol, node.left, flags, excludeFlags);
}
}

View file

@ -5562,6 +5562,7 @@ namespace ts {
export const enum AssignmentDeclarationKind {
None,
/// exports.name = expr
/// module.exports.name = expr
ExportsProperty,
/// module.exports = expr
ModuleExports,

View file

@ -0,0 +1,40 @@
//// [tests/cases/conformance/salsa/commonJSImportClassExpression.ts] ////
//// [main.js]
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
//// [mod1.js]
exports.K = class K {
values() {
}
};
//// [mod1.js]
"use strict";
exports.K = /** @class */ (function () {
function K() {
}
K.prototype.values = function () {
};
return K;
}());
//// [main.js]
"use strict";
var K = require("./mod1").K;
/** @param {K} k */
function f(k) {
k.values();
}
//// [mod1.d.ts]
export class K {
values(): void;
}
//// [main.d.ts]
export {};

View file

@ -0,0 +1,29 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : Symbol(K, Decl(main.js, 0, 7))
>require : Symbol(require)
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
/** @param {K} k */
function f(k) {
>f : Symbol(f, Decl(main.js, 0, 32))
>k : Symbol(k, Decl(main.js, 2, 11))
k.values()
>k.values : Symbol(K.values, Decl(mod1.js, 0, 21))
>k : Symbol(k, Decl(main.js, 2, 11))
>values : Symbol(K.values, Decl(mod1.js, 0, 21))
}
=== tests/cases/conformance/salsa/mod1.js ===
exports.K = class K {
>exports.K : Symbol(K, Decl(mod1.js, 0, 0))
>exports : Symbol(K, Decl(mod1.js, 0, 0))
>K : Symbol(K, Decl(mod1.js, 0, 0))
>K : Symbol(K, Decl(mod1.js, 0, 11))
values() {
>values : Symbol(K.values, Decl(mod1.js, 0, 21))
}
};

View file

@ -0,0 +1,33 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : typeof K
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
>require : any
>"./mod1" : "./mod1"
/** @param {K} k */
function f(k) {
>f : (k: K) => void
>k : K
k.values()
>k.values() : void
>k.values : () => void
>k : K
>values : () => void
}
=== tests/cases/conformance/salsa/mod1.js ===
exports.K = class K {
>exports.K = class K { values() { }} : typeof K
>exports.K : typeof K
>exports : typeof import("tests/cases/conformance/salsa/mod1")
>K : typeof K
>class K { values() { }} : typeof K
>K : typeof K
values() {
>values : () => void
}
};

View file

@ -0,0 +1,44 @@
//// [tests/cases/conformance/salsa/commonJSImportClassTypeReference.ts] ////
//// [main.js]
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
//// [mod1.js]
class K {
values() {
return new K()
}
}
exports.K = K;
//// [mod1.js]
"use strict";
var K = /** @class */ (function () {
function K() {
}
K.prototype.values = function () {
return new K();
};
return K;
}());
exports.K = K;
//// [main.js]
"use strict";
var K = require("./mod1").K;
/** @param {K} k */
function f(k) {
k.values();
}
//// [mod1.d.ts]
export class K {
values(): K;
}
//// [main.d.ts]
export {};

View file

@ -0,0 +1,34 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : Symbol(K, Decl(main.js, 0, 7))
>require : Symbol(require)
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
/** @param {K} k */
function f(k) {
>f : Symbol(f, Decl(main.js, 0, 32))
>k : Symbol(k, Decl(main.js, 2, 11))
k.values()
>k.values : Symbol(K.values, Decl(mod1.js, 0, 9))
>k : Symbol(k, Decl(main.js, 2, 11))
>values : Symbol(K.values, Decl(mod1.js, 0, 9))
}
=== tests/cases/conformance/salsa/mod1.js ===
class K {
>K : Symbol(K, Decl(mod1.js, 0, 0))
values() {
>values : Symbol(K.values, Decl(mod1.js, 0, 9))
return new K()
>K : Symbol(K, Decl(mod1.js, 0, 0))
}
}
exports.K = K;
>exports.K : Symbol(K, Decl(mod1.js, 4, 1))
>exports : Symbol(K, Decl(mod1.js, 4, 1))
>K : Symbol(K, Decl(mod1.js, 4, 1))
>K : Symbol(K, Decl(mod1.js, 0, 0))

View file

@ -0,0 +1,38 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : typeof K
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
>require : any
>"./mod1" : "./mod1"
/** @param {K} k */
function f(k) {
>f : (k: K) => void
>k : K
k.values()
>k.values() : K
>k.values : () => K
>k : K
>values : () => K
}
=== tests/cases/conformance/salsa/mod1.js ===
class K {
>K : K
values() {
>values : () => K
return new K()
>new K() : K
>K : typeof K
}
}
exports.K = K;
>exports.K = K : typeof K
>exports.K : typeof K
>exports : typeof import("tests/cases/conformance/salsa/mod1")
>K : typeof K
>K : typeof K

View file

@ -0,0 +1,48 @@
//// [tests/cases/conformance/salsa/commonJSImportNestedClassTypeReference.ts] ////
//// [main.js]
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
//// [mod1.js]
var NS = {}
NS.K =class {
values() {
return new NS.K()
}
}
exports.K = NS.K;
//// [mod1.js]
"use strict";
var NS = {};
NS.K = /** @class */ (function () {
function K() {
}
K.prototype.values = function () {
return new NS.K();
};
return K;
}());
exports.K = NS.K;
//// [main.js]
"use strict";
var K = require("./mod1").K;
/** @param {K} k */
function f(k) {
k.values();
}
//// [mod1.d.ts]
export var K: {
new (): {
values(): any;
};
};
//// [main.d.ts]
export {};

View file

@ -0,0 +1,43 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : Symbol(K, Decl(main.js, 0, 7))
>require : Symbol(require)
>"./mod1" : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0))
/** @param {K} k */
function f(k) {
>f : Symbol(f, Decl(main.js, 0, 32))
>k : Symbol(k, Decl(main.js, 2, 11))
k.values()
>k.values : Symbol(K.values, Decl(mod1.js, 1, 13))
>k : Symbol(k, Decl(main.js, 2, 11))
>values : Symbol(K.values, Decl(mod1.js, 1, 13))
}
=== tests/cases/conformance/salsa/mod1.js ===
var NS = {}
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
NS.K =class {
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
>K : Symbol(K, Decl(mod1.js, 0, 11))
values() {
>values : Symbol(K.values, Decl(mod1.js, 1, 13))
return new NS.K()
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
>K : Symbol(K, Decl(mod1.js, 0, 11))
}
}
exports.K = NS.K;
>exports.K : Symbol(K, Decl(mod1.js, 5, 1))
>exports : Symbol(K, Decl(mod1.js, 5, 1))
>K : Symbol(K, Decl(mod1.js, 5, 1))
>NS.K : Symbol(K, Decl(mod1.js, 0, 11))
>NS : Symbol(NS, Decl(mod1.js, 0, 3), Decl(mod1.js, 0, 11))
>K : Symbol(K, Decl(mod1.js, 0, 11))

View file

@ -0,0 +1,50 @@
=== tests/cases/conformance/salsa/main.js ===
const { K } = require("./mod1");
>K : typeof K
>require("./mod1") : typeof import("tests/cases/conformance/salsa/mod1")
>require : any
>"./mod1" : "./mod1"
/** @param {K} k */
function f(k) {
>f : (k: K) => void
>k : K
k.values()
>k.values() : K
>k.values : () => K
>k : K
>values : () => K
}
=== tests/cases/conformance/salsa/mod1.js ===
var NS = {}
>NS : typeof NS
>{} : {}
NS.K =class {
>NS.K =class { values() { return new NS.K() }} : typeof K
>NS.K : typeof K
>NS : typeof NS
>K : typeof K
>class { values() { return new NS.K() }} : typeof K
values() {
>values : () => K
return new NS.K()
>new NS.K() : K
>NS.K : typeof K
>NS : typeof NS
>K : typeof K
}
}
exports.K = NS.K;
>exports.K = NS.K : typeof K
>exports.K : typeof K
>exports : typeof import("tests/cases/conformance/salsa/mod1")
>K : typeof K
>NS.K : typeof K
>NS : typeof NS
>K : typeof K

View file

@ -66,9 +66,9 @@ function f(c, classic) {
>x : Symbol(K.x, Decl(mod.js, 1, 27))
classic.p
>classic.p : Symbol(Classic.p, Decl(mod.js, 5, 19))
>classic.p : Symbol(s.Classic.p, Decl(mod.js, 5, 19))
>classic : Symbol(classic, Decl(use.js, 9, 13))
>p : Symbol(Classic.p, Decl(mod.js, 5, 19))
>p : Symbol(s.Classic.p, Decl(mod.js, 5, 19))
}

View file

@ -58,11 +58,11 @@ k.x
>x : number
var classic = new s.Classic()
>classic : Classic
>new s.Classic() : Classic
>s.Classic : typeof Classic
>classic : s.Classic
>new s.Classic() : s.Classic
>s.Classic : typeof s.Classic
>s : typeof s
>Classic : typeof Classic
>Classic : typeof s.Classic
/** @param {s.n.K} c
@ -70,7 +70,7 @@ var classic = new s.Classic()
function f(c, classic) {
>f : (c: K, classic: s.Classic) => void
>c : K
>classic : Classic
>classic : s.Classic
c.x
>c.x : number
@ -79,7 +79,7 @@ function f(c, classic) {
classic.p
>classic.p : number
>classic : Classic
>classic : s.Classic
>p : number
}

View file

@ -13,7 +13,7 @@
"containerName": "",
"fileName": "/b.js",
"kind": "alias",
"name": "(alias) (property) f: () => void\nimport f",
"name": "(alias) function f(): void\nimport f",
"textSpan": {
"start": 8,
"length": 1
@ -36,16 +36,8 @@
"kind": "space"
},
{
"text": "(",
"kind": "punctuation"
},
{
"text": "property",
"kind": "text"
},
{
"text": ")",
"kind": "punctuation"
"text": "function",
"kind": "keyword"
},
{
"text": " ",
@ -55,14 +47,6 @@
"text": "f",
"kind": "aliasName"
},
{
"text": ":",
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "(",
"kind": "punctuation"
@ -72,11 +56,7 @@
"kind": "punctuation"
},
{
"text": " ",
"kind": "space"
},
{
"text": "=>",
"text": ":",
"kind": "punctuation"
},
{

View file

@ -4,8 +4,12 @@ function foo() {
module.exports = exports = function (o) {
return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
};
exports.methods = methods;
}
const m = function () {
// I have no idea what to put here
}
exports.methods = m;
}
//// [index.js]
// @ts-nocheck
@ -13,13 +17,17 @@ function foo() {
module.exports = exports = function (o) {
return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
};
exports.methods = methods;
var m = function () {
// I have no idea what to put here
};
exports.methods = m;
}
//// [index.d.ts]
declare function _exports(o: any): any;
declare namespace _exports {
const methods: any;
export { m as methods };
}
export = _exports;
declare function m(): void;

View file

@ -16,7 +16,14 @@ function foo() {
>o : Symbol(o, Decl(index.js, 2, 41))
};
exports.methods = methods;
>exports : Symbol(methods, Decl(index.js, 4, 6))
>methods : Symbol(methods, Decl(index.js, 4, 6))
const m = function () {
>m : Symbol(m, Decl(index.js, 5, 9))
// I have no idea what to put here
}
exports.methods = m;
>exports : Symbol(methods, Decl(index.js, 7, 5))
>methods : Symbol(methods, Decl(index.js, 7, 5))
>m : Symbol(m, Decl(index.js, 5, 9))
}

View file

@ -30,10 +30,17 @@ function foo() {
>descriptors : error
};
exports.methods = methods;
>exports.methods = methods : error
const m = function () {
>m : () => void
>function () { // I have no idea what to put here } : () => void
// I have no idea what to put here
}
exports.methods = m;
>exports.methods = m : () => void
>exports.methods : any
>exports : any
>methods : any
>methods : error
>m : () => void
}

View file

@ -130,6 +130,10 @@ export namespace f {
import self = f;
export { self };
}
export function i(): void;
export function j(): void;
declare class Cls {
}
/**
* @param {{x: string}} a
* @param {{y: typeof module.exports.b}} b
@ -146,7 +150,7 @@ export function g(a: {
* @param {{x: string}} a
* @param {{y: typeof module.exports.b}} b
*/
export function h(a: {
declare function hh(a: {
x: string;
}, b: {
y: {
@ -154,10 +158,4 @@ export function h(a: {
cat: string;
};
}): void;
export function i(): void;
export function ii(): void;
export function jj(): void;
export function j(): void;
declare class Cls {
}
export {};
export { hh as h, i as ii, j as jj };

View file

@ -1,55 +0,0 @@
tests/cases/conformance/jsdoc/declarations/file2.js(12,31): error TS2694: Namespace '"tests/cases/conformance/jsdoc/declarations/file".myTypes' has no exported member 'typeC'.
==== tests/cases/conformance/jsdoc/declarations/file2.js (1 errors) ====
const {myTypes} = require('./file.js');
/**
* @namespace testFnTypes
* @global
* @type {Object<string,*>}
*/
const testFnTypes = {
// SOME PROPS HERE
};
/** @typedef {boolean|myTypes.typeC} testFnTypes.input */
~~~~~
!!! error TS2694: Namespace '"tests/cases/conformance/jsdoc/declarations/file".myTypes' has no exported member 'typeC'.
/**
* @function testFn
* @description A test function.
* @param {testFnTypes.input} input - Input.
* @returns {number|null} Result.
*/
function testFn(input) {
if (typeof input === 'number') {
return 2 * input;
} else {
return null;
}
}
module.exports = {testFn, testFnTypes};
==== tests/cases/conformance/jsdoc/declarations/file.js (0 errors) ====
/**
* @namespace myTypes
* @global
* @type {Object<string,*>}
*/
const myTypes = {
// SOME PROPS HERE
};
/** @typedef {string|RegExp|Array<string|RegExp>} myTypes.typeA */
/**
* @typedef myTypes.typeB
* @property {myTypes.typeA} prop1 - Prop 1.
* @property {string} prop2 - Prop 2.
*/
/** @typedef {myTypes.typeB|Function} myTypes.typeC */
exports.myTypes = myTypes;

View file

@ -54,9 +54,28 @@ module.exports = {testFn, testFnTypes};
//// [file.d.ts]
export var myTypes: {
/**
* @namespace myTypes
* @global
* @type {Object<string,*>}
*/
export const myTypes: {
[x: string]: any;
};
export namespace myTypes {
type typeA = string | RegExp | (string | RegExp)[];
type typeB = {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
/**
* - Prop 2.
*/
prop2: string;
};
type typeC = Function | typeB;
}
//// [file2.d.ts]
/** @typedef {boolean|myTypes.typeC} testFnTypes.input */
/**
@ -65,7 +84,16 @@ export var myTypes: {
* @param {testFnTypes.input} input - Input.
* @returns {number|null} Result.
*/
export function testFn(input: any): number | null;
export function testFn(input: boolean | Function | {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
/**
* - Prop 2.
*/
prop2: string;
}): number | null;
/**
* @namespace testFnTypes
* @global
@ -75,5 +103,14 @@ export const testFnTypes: {
[x: string]: any;
};
export namespace testFnTypes {
type input = any;
type input = boolean | Function | {
/**
* - Prop 1.
*/
prop1: string | RegExp | (string | RegExp)[];
/**
* - Prop 2.
*/
prop2: string;
};
}

View file

@ -27,18 +27,18 @@ const testFnTypes = {
*/
function testFn(input) {
>testFn : (input: testFnTypes.input) => number | null
>input : any
>input : boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }
if (typeof input === 'number') {
>typeof input === 'number' : boolean
>typeof input : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
>input : any
>input : boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }
>'number' : "number"
return 2 * input;
>2 * input : number
>2 : 2
>input : number
>input : never
} else {
return null;
@ -47,12 +47,12 @@ function testFn(input) {
}
module.exports = {testFn, testFnTypes};
>module.exports = {testFn, testFnTypes} : { testFn: (input: any) => number; testFnTypes: { [x: string]: any; }; }
>module.exports : { testFn: (input: any) => number; testFnTypes: { [x: string]: any; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/file2\"": { testFn: (input: any) => number; testFnTypes: { [x: string]: any; }; }; }
>exports : { testFn: (input: any) => number; testFnTypes: { [x: string]: any; }; }
>{testFn, testFnTypes} : { testFn: (input: any) => number; testFnTypes: { [x: string]: any; }; }
>testFn : (input: any) => number
>module.exports = {testFn, testFnTypes} : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>module.exports : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>module : { "\"tests/cases/conformance/jsdoc/declarations/file2\"": { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }; }
>exports : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>{testFn, testFnTypes} : { testFn: (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number; testFnTypes: { [x: string]: any; }; }
>testFn : (input: boolean | Function | { prop1: string | RegExp | (string | RegExp)[]; prop2: string; }) => number
>testFnTypes : { [x: string]: any; }
=== tests/cases/conformance/jsdoc/declarations/file.js ===

View file

@ -19,11 +19,11 @@ module.exports.C = C
/** @param {X} c */
function demo(c) {
>demo : (c: X) => void
>c : C
>c : import("tests/cases/conformance/jsdoc/mod1").C
c.s
>c.s : () => void
>c : C
>c : import("tests/cases/conformance/jsdoc/mod1").C
>s : () => void
}

View file

@ -297,5 +297,5 @@ exports.wrapSync = exports.selectSeries = exports.selectLimit = exports.select =
>exports.apply : Symbol(apply, Decl(a.js, 0, 1900))
>exports : Symbol(apply, Decl(a.js, 0, 1900))
>apply : Symbol(apply, Decl(a.js, 0, 1900))
>undefined : Symbol(undefined)
>undefined : Symbol(apply)

View file

@ -393,8 +393,8 @@ exports.wrapSync = exports.selectSeries = exports.selectLimit = exports.select =
>exports : typeof import("tests/cases/conformance/jsdoc/a")
>applyEach : any
>exports.apply = undefined : undefined
>exports.apply : any
>exports.apply : undefined
>exports : typeof import("tests/cases/conformance/jsdoc/a")
>apply : any
>apply : undefined
>undefined : undefined

View file

@ -6,22 +6,22 @@ const x = require("./lateBoundAssignmentDeclarationSupport4.js");
>"./lateBoundAssignmentDeclarationSupport4.js" : "./lateBoundAssignmentDeclarationSupport4.js"
const inst = new x.F();
>inst : F
>new x.F() : F
>x.F : typeof F
>inst : x.F
>new x.F() : x.F
>x.F : typeof x.F
>x : typeof x
>F : typeof F
>F : typeof x.F
const y = inst["my-fake-sym"];
>y : any
>inst["my-fake-sym"] : any
>inst : F
>inst : x.F
>"my-fake-sym" : "my-fake-sym"
const z = inst[x.S];
>z : any
>inst[x.S] : any
>inst : F
>inst : x.F
>x.S : unique symbol
>x : typeof x
>S : unique symbol

View file

@ -6,22 +6,22 @@ const x = require("./lateBoundAssignmentDeclarationSupport5.js");
>"./lateBoundAssignmentDeclarationSupport5.js" : "./lateBoundAssignmentDeclarationSupport5.js"
const inst = new x.F();
>inst : F
>new x.F() : F
>x.F : typeof F
>inst : x.F
>new x.F() : x.F
>x.F : typeof x.F
>x : typeof x
>F : typeof F
>F : typeof x.F
const y = inst["my-fake-sym"];
>y : any
>inst["my-fake-sym"] : any
>inst : F
>inst : x.F
>"my-fake-sym" : "my-fake-sym"
const z = inst[x.S];
>z : any
>inst[x.S] : any
>inst : F
>inst : x.F
>x.S : unique symbol
>x : typeof x
>S : unique symbol

View file

@ -6,22 +6,22 @@ const x = require("./lateBoundAssignmentDeclarationSupport6.js");
>"./lateBoundAssignmentDeclarationSupport6.js" : "./lateBoundAssignmentDeclarationSupport6.js"
const inst = new x.F();
>inst : F
>new x.F() : F
>x.F : typeof F
>inst : x.F
>new x.F() : x.F
>x.F : typeof x.F
>x : typeof x
>F : typeof F
>F : typeof x.F
const y = inst["my-fake-sym"];
>y : any
>inst["my-fake-sym"] : any
>inst : F
>inst : x.F
>"my-fake-sym" : "my-fake-sym"
const z = inst[x.S];
>z : any
>inst[x.S] : any
>inst : F
>inst : x.F
>x.S : unique symbol
>x : typeof x
>S : unique symbol

View file

@ -9,7 +9,7 @@ const y = x.F["my-fake-sym"];
>x.F : Symbol(x.F, Decl(lateBoundAssignmentDeclarationSupport7.js, 6, 15))
>x : Symbol(x, Decl(usage.js, 0, 5))
>F : Symbol(x.F, Decl(lateBoundAssignmentDeclarationSupport7.js, 6, 15))
>"my-fake-sym" : Symbol(F.F[_str], Decl(lateBoundAssignmentDeclarationSupport7.js, 5, 15))
>"my-fake-sym" : Symbol(x.F.F[_str], Decl(lateBoundAssignmentDeclarationSupport7.js, 5, 15))
const z = x.F[x.S];
>z : Symbol(z, Decl(usage.js, 2, 5))

View file

@ -8,17 +8,17 @@ const x = require("./lateBoundAssignmentDeclarationSupport7.js");
const y = x.F["my-fake-sym"];
>y : string
>x.F["my-fake-sym"] : string
>x.F : typeof F
>x.F : typeof x.F
>x : typeof x
>F : typeof F
>F : typeof x.F
>"my-fake-sym" : "my-fake-sym"
const z = x.F[x.S];
>z : string
>x.F[x.S] : string
>x.F : typeof F
>x.F : typeof x.F
>x : typeof x
>F : typeof F
>F : typeof x.F
>x.S : unique symbol
>x : typeof x
>S : unique symbol

View file

@ -17,5 +17,5 @@ module.exports.D = class D { }
>module : Symbol(module, Decl(bug24024.js, 1, 31))
>exports : Symbol("tests/cases/conformance/salsa/bug24024", Decl(bug24024.js, 0, 0))
>D : Symbol(wat.D, Decl(bug24024.js, 2, 27))
>D : Symbol(D, Decl(bug24024.js, 3, 18))
>D : Symbol(wat.D, Decl(bug24024.js, 3, 18))

View file

@ -15,12 +15,12 @@ module.exports = class C {}
>C : typeof wat
module.exports.D = class D { }
>module.exports.D = class D { } : typeof D
>module.exports.D : typeof D
>module.exports.D = class D { } : typeof wat.D
>module.exports.D : typeof wat.D
>module.exports : typeof wat
>module : { "\"tests/cases/conformance/salsa/bug24024\"": typeof wat; }
>exports : typeof wat
>D : typeof D
>class D { } : typeof D
>D : typeof D
>D : typeof wat.D
>class D { } : typeof wat.D
>D : typeof wat.D

View file

@ -73,8 +73,8 @@ function f(c, classic) {
>x : Symbol(C.x, Decl(mod.js, 1, 35))
classic.p
>classic.p : Symbol(Classic.p, Decl(mod.js, 5, 19))
>classic.p : Symbol(s.Classic.p, Decl(mod.js, 5, 19))
>classic : Symbol(classic, Decl(use.js, 9, 13))
>p : Symbol(Classic.p, Decl(mod.js, 5, 19))
>p : Symbol(s.Classic.p, Decl(mod.js, 5, 19))
}

View file

@ -65,11 +65,11 @@ k.x
>x : number
var classic = new s.Classic()
>classic : Classic
>new s.Classic() : Classic
>s.Classic : typeof Classic
>classic : s.Classic
>new s.Classic() : s.Classic
>s.Classic : typeof s.Classic
>s : typeof s
>Classic : typeof Classic
>Classic : typeof s.Classic
/** @param {s.n.K} c
@ -77,7 +77,7 @@ var classic = new s.Classic()
function f(c, classic) {
>f : (c: C, classic: s.Classic) => void
>c : C
>classic : Classic
>classic : s.Classic
c.x
>c.x : number
@ -86,7 +86,7 @@ function f(c, classic) {
classic.p
>classic.p : number
>classic : Classic
>classic : s.Classic
>p : number
}

View file

@ -1,7 +1,5 @@
tests/cases/conformance/jsdoc/mod1.js(3,23): error TS2300: Duplicate identifier 'Foo'.
tests/cases/conformance/jsdoc/mod1.js(4,7): error TS2300: Duplicate identifier 'Foo'.
tests/cases/conformance/jsdoc/mod1.js(6,23): error TS2300: Duplicate identifier 'Bar'.
tests/cases/conformance/jsdoc/mod1.js(7,9): error TS2300: Duplicate identifier 'Bar'.
tests/cases/conformance/jsdoc/mod1.js(9,23): error TS2300: Duplicate identifier 'Baz'.
tests/cases/conformance/jsdoc/mod1.js(11,5): error TS2300: Duplicate identifier 'Baz'.
@ -14,7 +12,7 @@ tests/cases/conformance/jsdoc/mod1.js(11,5): error TS2300: Duplicate identifier
var bb;
var bbb = new mod.Baz();
==== tests/cases/conformance/jsdoc/mod1.js (6 errors) ====
==== tests/cases/conformance/jsdoc/mod1.js (4 errors) ====
// error
/** @typedef {number} Foo */
@ -25,11 +23,7 @@ tests/cases/conformance/jsdoc/mod1.js(11,5): error TS2300: Duplicate identifier
!!! error TS2300: Duplicate identifier 'Foo'.
/** @typedef {number} Bar */
~~~
!!! error TS2300: Duplicate identifier 'Bar'.
exports.Bar = class { }
~~~
!!! error TS2300: Duplicate identifier 'Bar'.
/** @typedef {number} Baz */
~~~

View file

@ -25,9 +25,9 @@ class Foo { } // should error
/** @typedef {number} Bar */
exports.Bar = class { }
>exports.Bar : Symbol(Bar, Decl(mod1.js, 3, 13))
>exports : Symbol(Bar, Decl(mod1.js, 3, 13))
>Bar : Symbol(Bar, Decl(mod1.js, 3, 13))
>exports.Bar : Symbol(Bar, Decl(mod1.js, 3, 13), Decl(mod1.js, 5, 4))
>exports : Symbol(Bar, Decl(mod1.js, 3, 13), Decl(mod1.js, 5, 4))
>Bar : Symbol(Bar, Decl(mod1.js, 3, 13), Decl(mod1.js, 5, 4))
/** @typedef {number} Baz */
module.exports = {

View file

@ -1,7 +1,7 @@
=== tests/cases/conformance/jsdoc/use.js ===
var mod = require('./mod1.js');
>mod : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; }
>require('./mod1.js') : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; }
>mod : { Baz: typeof Baz; Bar: typeof mod.Bar; Quid: number; } | { Quack: number; Bar: typeof mod.Bar; Quid: number; }
>require('./mod1.js') : { Baz: typeof Baz; Bar: typeof mod.Bar; Quid: number; } | { Quack: number; Bar: typeof mod.Bar; Quid: number; }
>require : any
>'./mod1.js' : "./mod1.js"
@ -17,7 +17,7 @@ var bbb = new mod.Baz();
>bbb : any
>new mod.Baz() : any
>mod.Baz : any
>mod : { Baz: typeof Baz; Bar: typeof Bar; Quid: number; } | { Quack: number; Bar: typeof Bar; Quid: number; }
>mod : { Baz: typeof Baz; Bar: typeof mod.Bar; Quid: number; } | { Quack: number; Bar: typeof mod.Bar; Quid: number; }
>Baz : any
=== tests/cases/conformance/jsdoc/mod1.js ===

View file

@ -8,5 +8,8 @@ function foo() {
module.exports = exports = function (o) {
return (o == null) ? create(base) : defineProperties(Object(o), descriptors);
};
exports.methods = methods;
}
const m = function () {
// I have no idea what to put here
}
exports.methods = m;
}

View file

@ -0,0 +1,18 @@
// @allowJs: true
// @checkJs: true
// @strict: true
// @outDir: out
// @declaration: true
// @filename: main.js
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
// @filename: mod1.js
exports.K = class K {
values() {
}
};

View file

@ -0,0 +1,20 @@
// @allowJs: true
// @checkJs: true
// @strict: true
// @outDir: out
// @declaration: true
// @filename: main.js
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
// @filename: mod1.js
class K {
values() {
return new K()
}
}
exports.K = K;

View file

@ -0,0 +1,21 @@
// @allowJs: true
// @checkJs: true
// @strict: true
// @outDir: out
// @declaration: true
// @filename: main.js
const { K } = require("./mod1");
/** @param {K} k */
function f(k) {
k.values()
}
// @filename: mod1.js
var NS = {}
NS.K =class {
values() {
return new NS.K()
}
}
exports.K = NS.K;

View file

@ -10,7 +10,7 @@
////[|A|];
const [r0Def, r0, r1Def, r1, r2] = test.ranges();
const defs = { definition: "class A\n(property) A: typeof A", ranges: [r0] };
const imports = { definition: "(alias) class A\n(alias) (property) A: typeof A\nimport A", ranges: [r1, r2] };
const defs = { definition: "(alias) (local class) A\nimport A", ranges: [r0] };
const imports = { definition: "(alias) (local class) A\nimport A", ranges: [r1, r2] };
verify.referenceGroups([r0], [defs, imports]);
verify.referenceGroups([r1, r2], [imports, defs]);

View file

@ -30,11 +30,11 @@ verify.referenceGroups(r0, [
{ definition: "(alias) (local class) export=\nimport export=", ranges: [r3] },
]);
verify.referenceGroups([r1, r5], [
{ definition: "class D\n(property) D: typeof D", ranges: [r1, r5, r5] }, // TODO: should only reference r5 once
{ definition: "(alias) (local class) D\nimport D", ranges: [r1, r5] },
]);
verify.referenceGroups(r2, [
{ definition: "(local class) D", ranges: [r2] },
{ definition: "class D\n(property) D: typeof D", ranges: [r5] },
{ definition: "(alias) (local class) D\nimport D", ranges: [r5] },
]);
verify.referenceGroups([r3, r4], [
{ definition: 'module "/a"', ranges: [r4, rModule] },

View file

@ -2,10 +2,10 @@
// @allowjs: true
// @Filename: a.js
//// class Class {
//// class /*classDefinition*/Class {
//// f;
//// }
//// module.exports./*classDefinition*/Class = Class;
//// module.exports.Class = Class;
// @Filename: b.js
////const { Class } = require("./a");

View file

@ -17,5 +17,5 @@
const entry = (text: string): FourSlashInterface.ExpectedCompletionEntry => ({ name: "foo", text, documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] });
verify.completions(
{ marker: "1", includes: entry("var foo: (p1: string) => void") },
{ marker: "2", exact: entry("(property) a.foo: (p1: string) => void") },
{ marker: "2", exact: entry("(alias) var foo: (p1: string) => void\nimport a.foo") },
);

View file

@ -16,5 +16,5 @@
verify.completions(
{ marker: "1", includes: { name: "foo", text: "var foo: (p1: string) => void", documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] } },
{ marker: "2", exact: { name: "foo", text: "(property) a.foo: (p1: string) => void", documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] } },
{ marker: "2", exact: { name: "foo", text: "(alias) var foo: (p1: string) => void\nimport a.foo", documentation: "Modify the parameter", tags: [{ name: "param", text: "p1" }] } },
);

View file

@ -16,5 +16,5 @@
////import f from "./a"
/////**/f
verify.quickInfoAt("", `(alias) (property) f: (t: string) => void
import f`, "Run this function"); // Passes
verify.quickInfoAt("", `(alias) function f(t: string): void
import f`, "Run this function"); // Passes

View file

@ -18,5 +18,5 @@
////import f from "./a"
/////**/f
verify.quickInfoAt("", `(alias) (property) f: (t: string) => void
import f`, "Run this function"); // Passes
verify.quickInfoAt("", `(alias) function f(t: string): void
import f`, "Run this function"); // Passes