Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "@ws/app", "type": "module" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { f, Bus } from '@ws/lib';
import { g } from '@ws/lib/sub';
import { deep } from 'ws-tools/deep';
// Control: a package this repository does not declare stays unresolved.
import { outside } from 'not-in-this-repo';

export function run() {
f();
g();
deep();
new Bus().publish('k');
return outside();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@ws/lib",
"main": "./dist/index.js",
"exports": {
".": { "import": "./dist/index.mjs", "require": "./dist/index.js" },
"./sub": "./dist/sub/index.js"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function f() {
return 1;
}

export class Bus {
publish(key) {
return key;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function g() {
return 2;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "ws-tools", "main": "dist/index.js" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function deep() {
return 3;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import_cause bundler-alias/legacy/app.js:4:10 Lib/extra not_staged
import_cause bundler-alias/legacy/app.js:5:10 Loose/extra not_staged
import_cause bundler-alias/legacy/webpack.config.cjs:1:14 path builtin
import_cause bundler-alias/src/pages/Home.js:6:10 @utils/date not_staged
import_cause bundler-alias/vite.config.js:1:10 vite not_staged
import_cause bundler-alias/vite.config.js:2:1 path builtin
import_cause bundler-alias/vite.config.js:3:10 node:url builtin
import_cause bundler-alias/vite.config.js:3:25 node:url builtin
import_cause framework-alias/other/probe.js:2:10 $lib/helper not_staged
import_cause jsconfig-paths/noalias/probe.js:2:10 @/check not_staged
import_cause workspace-package/apps/app/src/main.js:5:10 not-in-this-repo not_staged
package_entry @ws/app . [] DEFAULT_INDEX index.js MISSING_FILE -> -
package_entry @ws/lib . [] MAIN dist/index.js MISSING_FILE -> -
package_entry @ws/lib . [import] EXPORTS dist/index.mjs MISSING_FILE -> -
package_entry @ws/lib . [require] EXPORTS dist/index.js MISSING_FILE -> -
package_entry @ws/lib ./sub [] EXPORTS dist/sub/index.js MISSING_FILE -> -
package_entry bundler-alias-fixture . [] DEFAULT_INDEX index.js MISSING_FILE -> -
package_entry framework-alias-fixture . [] DEFAULT_INDEX index.js MISSING_FILE -> -
package_entry path-alias-fixture . [] DEFAULT_INDEX index.js MISSING_FILE -> -
package_entry ws-tools . [] MAIN dist/index.js MISSING_FILE -> -
unresolved bundler-alias/legacy/app.js:10:3 FUNCTION_CALL loose callee_untyped
unresolved bundler-alias/legacy/app.js:9:3 FUNCTION_CALL extra callee_untyped
unresolved bundler-alias/legacy/lib/util/trim.js:2:10 METHOD_CALL trim receiver_untyped
unresolved bundler-alias/legacy/webpack.config.cjs:7:13 METHOD_CALL resolve no_target
unresolved bundler-alias/legacy/webpack.config.cjs:8:13 METHOD_CALL join no_target
unresolved bundler-alias/shared/fmt.js:2:10 METHOD_CALL toFixed receiver_untyped
unresolved bundler-alias/src/pages/Home.js:10:3 FUNCTION_CALL scoped callee_untyped
unresolved bundler-alias/src/utils/date.js:2:10 FUNCTION_CALL String no_target
unresolved bundler-alias/vite.config.js:10:18 FUNCTION_CALL fileURLToPath no_target
unresolved bundler-alias/vite.config.js:10:32 CONSTRUCTOR_CALL URL no_target
unresolved bundler-alias/vite.config.js:6:16 FUNCTION_CALL defineConfig callee_untyped
unresolved bundler-alias/vite.config.js:9:12 METHOD_CALL resolve receiver_untyped
unresolved framework-alias/other/probe.js:5:10 FUNCTION_CALL helper callee_untyped
unresolved jsconfig-paths/noalias/probe.js:5:10 FUNCTION_CALL checkA callee_untyped
unresolved workspace-package/apps/app/src/main.js:12:10 FUNCTION_CALL outside callee_untyped
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
bundler-alias/legacy/app.js:10:3 FUNCTION_CALL loose -> ambiguous_unknown -
bundler-alias/legacy/app.js:11:10 FUNCTION_CALL trim -> known_edge bundler-alias/legacy/lib/util/trim.js:1:1 trim
bundler-alias/legacy/app.js:8:3 FUNCTION_CALL boot -> known_edge bundler-alias/legacy/lib/index.js:1:1 boot
bundler-alias/legacy/app.js:9:3 FUNCTION_CALL extra -> ambiguous_unknown -
bundler-alias/legacy/lib/util/trim.js:2:10 METHOD_CALL s.trim -> ambiguous_unknown -
bundler-alias/legacy/webpack.config.cjs:7:13 METHOD_CALL path.resolve -> ambient_terminal -
bundler-alias/legacy/webpack.config.cjs:8:13 METHOD_CALL path.join -> ambient_terminal -
bundler-alias/mapped/probe.js:5:10 FUNCTION_CALL fmtDate -> known_edge bundler-alias/mapped/own/date.js:1:1 fmtDate
bundler-alias/shared/fmt.js:2:10 METHOD_CALL n.toFixed -> ambiguous_unknown -
bundler-alias/src/pages/Home.js:10:3 FUNCTION_CALL scoped -> ambiguous_unknown -
bundler-alias/src/pages/Home.js:11:10 FUNCTION_CALL fmtDate -> known_edge bundler-alias/src/utils/date.js:1:1 fmtDate
bundler-alias/src/pages/Home.js:9:3 FUNCTION_CALL fmtMoney -> known_edge bundler-alias/shared/fmt.js:1:1 fmtMoney
bundler-alias/src/utils/date.js:2:10 FUNCTION_CALL String -> ambient_terminal -
bundler-alias/vite.config.js:10:18 FUNCTION_CALL fileURLToPath -> ambient_terminal -
bundler-alias/vite.config.js:10:32 CONSTRUCTOR_CALL URL -> ambient_terminal -
bundler-alias/vite.config.js:6:16 FUNCTION_CALL defineConfig -> ambiguous_unknown -
bundler-alias/vite.config.js:6:16 FUNCTION_CALL defineConfig -> callback_registered bundler-alias/vite.config.js:6:29 <arrow>
bundler-alias/vite.config.js:9:12 METHOD_CALL path.resolve -> ambient_terminal -
framework-alias/kit/src/routes/page.js:10:10 FUNCTION_CALL post -> known_edge framework-alias/kit/src/lib/api.js:5:1 post
framework-alias/kit/src/routes/page.js:6:10 METHOD_CALL api.get -> known_edge framework-alias/kit/src/lib/api.js:1:1 get
framework-alias/nuxt/server/api/price.js:6:10 FUNCTION_CALL formatPrice -> known_edge framework-alias/nuxt/utils/price.js:1:1 formatPrice
framework-alias/nuxt/server/api/price.js:6:27 FUNCTION_CALL viaAt -> known_edge framework-alias/nuxt/utils/price.js:1:1 formatPrice
framework-alias/nuxt4/app/pages/index.js:5:10 FUNCTION_CALL formatDate -> known_edge framework-alias/nuxt4/app/utils/date.js:1:1 formatDate
framework-alias/other/probe.js:5:10 FUNCTION_CALL helper -> ambiguous_unknown -
framework-alias/own/probe.js:5:10 FUNCTION_CALL pick -> known_edge framework-alias/own/shared/util.js:1:1 pick
jsconfig-paths/app.js:11:10 FUNCTION_CALL checkB -> known_edge jsconfig-paths/lib/check.js:5:1 checkB
jsconfig-paths/app.js:7:10 FUNCTION_CALL checkA -> known_edge jsconfig-paths/lib/check.js:1:1 checkA
jsconfig-paths/noalias/probe.js:5:10 FUNCTION_CALL checkA -> ambiguous_unknown -
jsconfig-paths/remix/app/route.js:5:10 FUNCTION_CALL getNote -> known_edge jsconfig-paths/remix/app/models/note.server.js:1:1 getNote
workspace-package/apps/app/src/main.js:10:3 FUNCTION_CALL deep -> known_edge workspace-package/packages/tools/src/deep.js:1:1 deep
workspace-package/apps/app/src/main.js:11:3 CONSTRUCTOR_CALL Bus -> implicit_constructor -
workspace-package/apps/app/src/main.js:11:3 METHOD_CALL new Bus().publish -> known_edge workspace-package/packages/lib/src/index.js:6:3 publish
workspace-package/apps/app/src/main.js:12:10 FUNCTION_CALL outside -> ambiguous_unknown -
workspace-package/apps/app/src/main.js:8:3 FUNCTION_CALL f -> known_edge workspace-package/packages/lib/src/index.js:1:1 f
workspace-package/apps/app/src/main.js:9:3 FUNCTION_CALL g -> known_edge workspace-package/packages/lib/src/sub/index.js:1:1 g
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
bundler-alias/legacy/webpack.config.cjs:7:13 METHOD_CALL resolve LIB_AMBIENT_OK
bundler-alias/legacy/webpack.config.cjs:8:13 METHOD_CALL join LIB_AMBIENT_OK
bundler-alias/src/utils/date.js:2:10 FUNCTION_CALL String LIB_AMBIENT_OK
bundler-alias/vite.config.js:10:18 FUNCTION_CALL fileURLToPath LIB_AMBIENT_OK
bundler-alias/vite.config.js:10:32 CONSTRUCTOR_CALL URL LIB_AMBIENT_OK
bundler-alias/vite.config.js:6:16 FUNCTION_CALL defineConfig LIB_MISSED
bundler-alias/vite.config.js:9:12 METHOD_CALL resolve LIB_AMBIENT_OK
jsconfig-paths/app.js:11:10 FUNCTION_CALL checkB EXACT jsconfig-paths/lib/check.js:5:1
# defects: 0
3 changes: 0 additions & 3 deletions graph/test/javascript/expected/70-jsconfig-path-alias.diag

This file was deleted.

4 changes: 0 additions & 4 deletions graph/test/javascript/expected/70-jsconfig-path-alias.edges

This file was deleted.

This file was deleted.

21 changes: 0 additions & 21 deletions graph/test/javascript/expected/71-bundler-config-alias.diag

This file was deleted.

18 changes: 0 additions & 18 deletions graph/test/javascript/expected/71-bundler-config-alias.edges

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "@x/app", "private": true, "dependencies": { "@x/lib": "workspace:*", "tools": "workspace:*", "zod": "^3.0.0" } }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function local(): void {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { f, Bus, K } from '@x/lib';
import { g } from '@x/lib/sub';
import { isOn } from '@x/lib/feature/flags';
import { tool } from 'tools';
import { deep } from 'tools/deep';
// Control: a third-party package no workspace declares stays a library import.
import { z } from 'zod';

import { local } from './local';

export class S {
constructor(private bus: Bus) {}

run(): void {
f();
g();
this.bus.publish(K);
if (isOn('x')) {
tool();
}
deep();
local();
z.string();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// A third-party package, declared the way its own types would declare it.
declare module 'zod' {
export const z: { string(): unknown };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "ws-root", "private": true }
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "@x/lib",
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" },
"./sub": { "types": "./dist/sub/index.d.ts", "default": "./dist/sub/index.js" },
"./feature/*": { "types": "./dist/feature/*.d.ts", "default": "./dist/feature/*.js" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isOn(name: string): boolean {
return name !== '';
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function f(): void {}

export class Bus {
publish(key: string): void {}
}

export const K = 'k';
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function g(): void {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{ "name": "tools", "main": "dist/index.js" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function deep(): void {}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function tool(): void {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
packages:
- 'packages/*'
- 'apps/*'
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
known_edge FUNCTION_CALL S#run() @L15 -> packages/lib/src/index#f()
known_edge FUNCTION_CALL S#run() @L16 -> packages/lib/src/sub/index#g()
known_edge FUNCTION_CALL S#run() @L18 -> packages/lib/src/feature/flags#isOn(string)
known_edge FUNCTION_CALL S#run() @L19 -> packages/tools/src/index#tool()
known_edge FUNCTION_CALL S#run() @L21 -> packages/tools/src/deep#deep()
known_edge FUNCTION_CALL S#run() @L22 -> apps/app/src/local#local()
known_edge METHOD_CALL S#run() @L17 -> Bus#publish(string)
known_edge METHOD_CALL S#run() @L23 -> apps/app/types/zod#string()
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
── entry_point (2) ──
unimported_module apps/app/src/main#<module> main.ts:1
unimported_module apps/app/types/zod#<module> zod.ts:1
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
known_edge read S#run() -> S#bus
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
85-workspace-package-import [fields]
precision 1.0000 (1 correct, 0 wrong)
recall 1.0000 (1 of 1 the compiler resolved)
sites 1 resolved 1 (100.0%)
tiers known_edge=1
access read=1
not scored: 0 rows whose target is not a client declaration
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
oracle=8 engine=8 agree=8 missing=0 (known 0, NEW 0) extra=0
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
known_edge METHOD_PARAM 0 S [METHOD_PARAM] -> Bus
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
85-workspace-package-import [types]
precision 1.0000 (1 correct, 0 wrong)
recall 1.0000 (1 of 1 the compiler resolved)
sites 1 resolved 1 (100.0%)
tiers known_edge=1
contexts METHOD_PARAM=1
not scored: 0 rows whose target is not a client declaration
26 changes: 26 additions & 0 deletions graph/test/typescript/ground-truth/tsc-program.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,32 @@ export function loadProgram(srcDir, libDir, toolName, programDir) {
}
}

// ── a WORKSPACE PACKAGE below the case root, imported by its name ───────────
// In a real monorepo the compiler reaches a sibling package through a node_modules
// link and the declarations its build wrote. A case holds neither, so the program is
// told where each named package's source is by the plainest convention there is: the
// package is `<dir>/src/index.ts`, and `<name>/x` is `<dir>/src/x`. Deliberately not
// the parser's rule (which reads main / types / exports): the two must agree on the
// answer without sharing the reasoning. A case with no nested package.json is unchanged.
const workspacePaths = {};
(function walk(d) {
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
const p = path.join(d, e.name);
if (e.isDirectory() && e.name !== 'node_modules') {
walk(p);
} else if (e.name === 'package.json' && d !== root) {
const name = JSON.parse(fs.readFileSync(p, 'utf-8')).name;
if (typeof name === 'string' && name !== '') {
workspacePaths[name] = [path.join(d, 'src', 'index.ts')];
workspacePaths[`${name}/*`] = [path.join(d, 'src', '*'), path.join(d, 'src', '*', 'index.ts')];
}
}
}
})(root);
if (Object.keys(workspacePaths).length > 0) {
options.paths = { ...workspacePaths, ...(options.paths ?? {}) };
}

const program = ts.createProgram(files, options);
const checker = program.getTypeChecker();
// CALLERS come only from the client. TARGETS may be either, which is what makes the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ export enum TsImportResolutionKind {
NODE_MODULES_SOURCE = 'NODE_MODULES_SOURCE',
/** Resolved through a package's `exports` map. */
PACKAGE_EXPORTS = 'PACKAGE_EXPORTS',
/**
* A package this repository declares, imported by its name: bound to the walked
* source its `main` / `types` / `exports` entry is built from.
*/
WORKSPACE_PACKAGE = 'WORKSPACE_PACKAGE',
/** Matched a `declare module "x"` in this analysis. No file, and none needed. */
AMBIENT_MODULE = 'AMBIENT_MODULE',
/** A Node builtin, with or without the `node:` prefix. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,11 @@ export interface JsFileExtractionOptions {
readonly projectModuleHashes: ReadonlyMap<string, string>;
/** Absolute path -> project-relative path, extension stripped. */
readonly toProjectRelative: (absolutePath: string) => string;
/**
* A bare specifier naming a package this repository declares -> the absolute path of
* the walked source module its entry is built from (`WorkspacePackages`).
*/
readonly resolveWorkspaceModule?: (specifier: string) => string | undefined;
/**
* How `sourceText` parses, when the file's extension cannot say: a `.vue`
* component's virtual script is JS or JSX by its `lang`, not by its name.
Expand Down Expand Up @@ -384,6 +389,7 @@ export function extractJavaScriptFile(options: JsFileExtractionOptions): JsFileF
typeHashByNode: declarations.typeHashByNode,
moduleInitMethodHash: declarations.moduleInitMethodHash,
toProjectRelative: options.toProjectRelative,
resolveWorkspaceModule: options.resolveWorkspaceModule,
projectModuleHashes: options.projectModuleHashes,
declarationTargetByName,
});
Expand Down
Loading
Loading