279 lines
12 KiB
Go
279 lines
12 KiB
Go
package fourslash_test
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/microsoft/typescript-go/internal/fourslash"
|
|
"github.com/microsoft/typescript-go/internal/testutil"
|
|
)
|
|
|
|
func TestGoToSourceAliasedImportExport(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare const foo: number;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
exports./*target*/foo = 1;
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { foo as /*importAlias*/bar } from "pkg";
|
|
bar;
|
|
// @Filename: /home/src/workspaces/project/reexport.ts
|
|
export { foo as /*reExportAlias*/bar } from "pkg";`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "importAlias", "reExportAlias")
|
|
}
|
|
|
|
func TestGoToSourceAliasedImportSpecifier(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
// import { original as alias } uses the propertyName branch.
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare function original(): string;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export function /*target*/original() { return "ok"; }
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { original as /*aliasedImport*/renamed } from "pkg";
|
|
renamed();`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "aliasedImport")
|
|
}
|
|
|
|
func TestGoToSourceCallThroughImport(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
// When calling an imported function, the checker returns both the import specifier
|
|
// (in the current file) and the call signature target (from .d.ts → mapped to .js).
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare class Widget {
|
|
constructor(name: string);
|
|
render(): void;
|
|
}
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export class /*targetWidget*/Widget {
|
|
constructor(name) { this.name = name; }
|
|
/*targetRender*/render() {}
|
|
}
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { Widget } from "pkg";
|
|
const w = new /*constructorCall*/Widget("test");
|
|
w./*methodCall*/render();`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "constructorCall", "methodCall")
|
|
}
|
|
|
|
func TestGoToSourceCallbackParam(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/@types/yargs/package.json
|
|
{
|
|
"name": "@types/yargs",
|
|
"version": "1.0.0",
|
|
"types": "./index.d.ts"
|
|
}
|
|
// @Filename: /home/src/workspaces/project/node_modules/@types/yargs/index.d.ts
|
|
export interface Yargs { positional(): Yargs; }
|
|
export declare function command(command: string, cb: (yargs: Yargs) => void): void;
|
|
// @Filename: /home/src/workspaces/project/node_modules/yargs/package.json
|
|
{
|
|
"name": "yargs",
|
|
"version": "1.0.0",
|
|
"main": "index.js"
|
|
}
|
|
// @Filename: /home/src/workspaces/project/node_modules/yargs/index.js
|
|
export function command(cmd, cb) { cb({ /*end*/positional: "This is obviously not even close to realistic" }); }
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { command } from "yargs";
|
|
command("foo", yargs => {
|
|
yargs.[|/*start*/positional|]();
|
|
});`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "start")
|
|
}
|
|
|
|
func TestGoToSourceReExportNames(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare function foo(): string;
|
|
export declare function bar(): number;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export function /*targetFoo*/foo() { return "ok"; }
|
|
export function /*targetBar*/bar() { return 42; }
|
|
// @Filename: /home/src/workspaces/project/reexport.ts
|
|
export { /*reExportFoo*/foo, /*reExportBar*/bar } from "pkg";
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { foo, bar } from [|"pkg"/*moduleSpecifier*/|];`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "reExportFoo", "reExportBar", "moduleSpecifier")
|
|
}
|
|
|
|
func TestGoToSourceReExportModuleSpecifier(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare function alpha(): string;
|
|
export declare function beta(): number;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export function /*targetAlpha*/alpha() { return "a"; }
|
|
export function /*targetBeta*/beta() { return 2; }
|
|
// @Filename: /home/src/workspaces/project/reexport.ts
|
|
export { alpha, beta } from [|"pkg"/*reExportSpecifier*/|];`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "reExportSpecifier")
|
|
}
|
|
|
|
func TestGoToSourceReExportedImplementation(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts", "type": "module" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export { foo } from "./foo";
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export { foo } from "./foo.js";
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/foo.d.ts
|
|
export declare function foo(): string;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/foo.js
|
|
export function /*target*/foo() { return "ok"; }
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { /*importName*/foo } from "pkg";
|
|
foo/*start*/();`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "importName", "start")
|
|
}
|
|
|
|
func TestGoToSourceImportFilteredByExternalDeclaration(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare function helper(): void;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export function /*target*/helper() {}
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { helper } from "pkg";
|
|
helper/*usage*/();
|
|
export { helper as /*reExport*/myHelper } from "pkg";`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "usage", "reExport")
|
|
}
|
|
|
|
func TestGoToSourceDtsReExport(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
// The .d.ts declaration itself re-exports from another module,
|
|
// so findContainingModuleSpecifier(declaration) finds that specifier.
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/impl.d.ts
|
|
export declare function helper(): void;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/impl.js
|
|
export function /*target*/helper() {}
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export { helper } from "./impl";
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export { helper } from "./impl.js";
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { helper } from "pkg";
|
|
helper/*usage*/();`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "usage")
|
|
}
|
|
|
|
func TestGoToSourceBarrelReExportChain(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
// index.js re-exports from impl.js, causing getForwardedImplementationFiles
|
|
// to follow the chain.
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/impl.js
|
|
export function /*target*/doWork() { return 42; }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/impl.d.ts
|
|
export declare function doWork(): number;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export { doWork } from "./impl";
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
export { doWork } from "./impl.js";
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { /*importName*/doWork } from "pkg";
|
|
doWork/*callSite*/();`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "importName", "callSite")
|
|
}
|
|
|
|
func TestGoToSourceCJSReExportViaDefineProperty(t *testing.T) {
|
|
t.Parallel()
|
|
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
|
|
const content = `// @moduleResolution: bundler
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/package.json
|
|
{ "name": "pkg", "main": "./index.js", "types": "./index.d.ts" }
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.d.ts
|
|
export declare function greet(name: string): string;
|
|
export declare enum TargetPopulation {
|
|
Team = "team",
|
|
Public = "public",
|
|
}
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/index.js
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TargetPopulation = exports.greet = void 0;
|
|
var impl_1 = require("./impl");
|
|
Object.defineProperty(exports, "greet", { enumerable: true, get: function () { return impl_1.greet; } });
|
|
var types_1 = require("./types");
|
|
Object.defineProperty(exports, "TargetPopulation", { enumerable: true, get: function () { return types_1.TargetPopulation; } });
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/impl.js
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.greet = void 0;
|
|
function /*greetImpl*/greet(name) { return "Hello, " + name; }
|
|
exports.greet = greet;
|
|
// @Filename: /home/src/workspaces/project/node_modules/pkg/types.js
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.TargetPopulation = void 0;
|
|
var /*targetPopulationImpl*/TargetPopulation;
|
|
(function (TargetPopulation) {
|
|
TargetPopulation["Team"] = "team";
|
|
TargetPopulation["Public"] = "public";
|
|
})(TargetPopulation || (exports.TargetPopulation = TargetPopulation = {}));
|
|
// @Filename: /home/src/workspaces/project/index.ts
|
|
import { /*namedImport*/greet, /*enumImport*/TargetPopulation } from "pkg";
|
|
greet/*call*/("world");
|
|
TargetPopulation/*enumAccess*/.Team;`
|
|
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
|
|
defer done()
|
|
f.VerifyBaselineGoToSourceDefinition(t, "namedImport", "enumImport", "call", "enumAccess")
|
|
}
|