@opensip-cli/lang-typescript 0.1.7 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/__tests__/program-service.test.d.ts +2 -0
- package/dist/__tests__/program-service.test.d.ts.map +1 -0
- package/dist/__tests__/program-service.test.js +97 -0
- package/dist/__tests__/program-service.test.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/program-service.d.ts +55 -0
- package/dist/program-service.d.ts.map +1 -0
- package/dist/program-service.js +106 -0
- package/dist/program-service.js.map +1 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -23,8 +23,8 @@ This package is published for the CLI and advanced plugin authors; most users sh
|
|
|
23
23
|
## Documentation
|
|
24
24
|
|
|
25
25
|
- 📚 Project docs: https://opensip.ai/docs/opensip-cli/
|
|
26
|
-
- 🧭 Package catalog (what every package does): https://github.com/opensip-ai/opensip-cli/blob/v0.1.
|
|
27
|
-
- 📦 Source: https://github.com/opensip-ai/opensip-cli/tree/v0.1.
|
|
26
|
+
- 🧭 Package catalog (what every package does): https://github.com/opensip-ai/opensip-cli/blob/v0.1.8/docs/public/70-reference/02-package-catalog.md
|
|
27
|
+
- 📦 Source: https://github.com/opensip-ai/opensip-cli/tree/v0.1.8/packages/languages/lang-typescript
|
|
28
28
|
|
|
29
29
|
## License
|
|
30
30
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-service.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/program-service.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { tmpdir } from 'node:os';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import * as ts from 'typescript';
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
|
6
|
+
import { createTypeCheckedProgram, isTypeNullable } from '../program-service.js';
|
|
7
|
+
let dir;
|
|
8
|
+
beforeEach(() => {
|
|
9
|
+
dir = mkdtempSync(join(tmpdir(), 'opensip-progsvc-'));
|
|
10
|
+
});
|
|
11
|
+
afterEach(() => {
|
|
12
|
+
rmSync(dir, { recursive: true, force: true });
|
|
13
|
+
});
|
|
14
|
+
function write(rel, content) {
|
|
15
|
+
const abs = join(dir, rel);
|
|
16
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
17
|
+
writeFileSync(abs, content);
|
|
18
|
+
return abs;
|
|
19
|
+
}
|
|
20
|
+
/** Map of bare-identifier call expressions → their resolved result type. */
|
|
21
|
+
function callTypes(sf, checker) {
|
|
22
|
+
const out = new Map();
|
|
23
|
+
const visit = (n) => {
|
|
24
|
+
if (ts.isCallExpression(n) && ts.isIdentifier(n.expression)) {
|
|
25
|
+
out.set(n.expression.text, checker.getTypeAtLocation(n));
|
|
26
|
+
}
|
|
27
|
+
ts.forEachChild(n, visit);
|
|
28
|
+
};
|
|
29
|
+
visit(sf);
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
/** Resolve the type of a top-level `const <name>` initializer site by name. */
|
|
33
|
+
function varType(sf, checker, name) {
|
|
34
|
+
for (const stmt of sf.statements) {
|
|
35
|
+
if (!ts.isVariableStatement(stmt))
|
|
36
|
+
continue;
|
|
37
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
38
|
+
if (ts.isIdentifier(decl.name) && decl.name.text === name) {
|
|
39
|
+
return checker.getTypeAtLocation(decl.name);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
throw new Error(`variable ${name} not found`);
|
|
44
|
+
}
|
|
45
|
+
describe('createTypeCheckedProgram', () => {
|
|
46
|
+
it('builds a bound Program that resolves real (non-null vs nullable) return types', () => {
|
|
47
|
+
const file = write('src/sample.ts', [
|
|
48
|
+
'export function getNullable(): string | null { return null; }',
|
|
49
|
+
'export function getMaybe(): number | undefined { return undefined; }',
|
|
50
|
+
"export function getSafe(): string { return ''; }",
|
|
51
|
+
'export function use() {',
|
|
52
|
+
' return [getNullable(), getMaybe(), getSafe()];',
|
|
53
|
+
'}',
|
|
54
|
+
].join('\n'));
|
|
55
|
+
const { checker, getSourceFile } = createTypeCheckedProgram([file], { projectRoot: dir });
|
|
56
|
+
const sf = getSourceFile(file);
|
|
57
|
+
expect(sf).toBeDefined();
|
|
58
|
+
const types = callTypes(sf, checker);
|
|
59
|
+
expect(isTypeNullable(types.get('getNullable'))).toBe(true);
|
|
60
|
+
expect(isTypeNullable(types.get('getMaybe'))).toBe(true);
|
|
61
|
+
expect(isTypeNullable(types.get('getSafe'))).toBe(false);
|
|
62
|
+
});
|
|
63
|
+
it('isTypeNullable fails open: `any`/`unknown` are not treated as nullable', () => {
|
|
64
|
+
const file = write('src/loose.ts', ['export const a: any = 1;', 'export const b: unknown = 1;'].join('\n'));
|
|
65
|
+
const { program, checker, getSourceFile } = createTypeCheckedProgram([file], {
|
|
66
|
+
projectRoot: dir,
|
|
67
|
+
});
|
|
68
|
+
expect(program.getSourceFiles().some((s) => s.fileName === file)).toBe(true);
|
|
69
|
+
const sf = getSourceFile(file);
|
|
70
|
+
expect(isTypeNullable(varType(sf, checker, 'a'))).toBe(false);
|
|
71
|
+
expect(isTypeNullable(varType(sf, checker, 'b'))).toBe(false);
|
|
72
|
+
});
|
|
73
|
+
it('honors an explicit tsconfig (strictNullChecks off → string|null reads non-nullable)', () => {
|
|
74
|
+
// A real project tsconfig with strict OFF: under it, `string | null` is the
|
|
75
|
+
// pre-strict `string` (null absorbed), so the service reflects the project's
|
|
76
|
+
// own type config rather than imposing strictness.
|
|
77
|
+
write('tsconfig.json', JSON.stringify({ compilerOptions: { strict: false } }));
|
|
78
|
+
const file = write('src/proj.ts', 'export const n: string | null = null;');
|
|
79
|
+
const built = createTypeCheckedProgram([file], {
|
|
80
|
+
projectRoot: dir,
|
|
81
|
+
tsconfigPath: 'tsconfig.json',
|
|
82
|
+
});
|
|
83
|
+
expect(built.tsconfigPath).toBeDefined();
|
|
84
|
+
const sf = built.getSourceFile(file);
|
|
85
|
+
expect(isTypeNullable(varType(sf, built.checker, 'n'))).toBe(false);
|
|
86
|
+
});
|
|
87
|
+
it('degrades gracefully when no tsconfig is found (fallback options, tsconfigPath undefined)', () => {
|
|
88
|
+
const file = write('src/orphan.ts', 'export const m: string | null = null;');
|
|
89
|
+
const built = createTypeCheckedProgram([file], { projectRoot: dir });
|
|
90
|
+
// The temp dir has no tsconfig and is outside any project tree.
|
|
91
|
+
expect(built.tsconfigPath).toBeUndefined();
|
|
92
|
+
const sf = built.getSourceFile(file);
|
|
93
|
+
// Fallback options enable strict, so `string | null` still reads as nullable.
|
|
94
|
+
expect(isTypeNullable(varType(sf, built.checker, 'm'))).toBe(true);
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
//# sourceMappingURL=program-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-service.test.js","sourceRoot":"","sources":["../../src/__tests__/program-service.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export { stripStrings, stripComments } from './strip.js';
|
|
|
7
7
|
export { filterContent } from './filter.js';
|
|
8
8
|
export type { FilteredContent } from './filter.js';
|
|
9
9
|
export { discoverTypescriptWorkspaceUnits } from './workspace-units.js';
|
|
10
|
+
export { createTypeCheckedProgram, isTypeNullable } from './program-service.js';
|
|
11
|
+
export type { TypeCheckedProgram, CreateTypeCheckedProgramOptions } from './program-service.js';
|
|
10
12
|
export { findEnclosingFunction, findEnclosingFunctionBody, getEnclosingFunctionName, findEnclosingScope, isAsync, isInAsyncContext, isInsideConditionalBlock, } from './function-scope.js';
|
|
11
13
|
export type { FunctionLikeNode } from './function-scope.js';
|
|
12
14
|
export { getSharedSourceFile, walkNodes, getIdentifierName, getPropertyChain, getLineNumber, getColumn, isPropertyAccess, isLiteral, isInStringLiteral, findCallExpressions, findBinaryExpressions, findTemplateLiterals, isInComment, countUnescapedBackticks, } from './ast-utilities.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,EAAE,EAAE,CAAC;AAEd,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,EAAE,EAAE,CAAC;AAEd,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAIxE,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAChF,YAAY,EAAE,kBAAkB,EAAE,+BAA+B,EAAE,MAAM,sBAAsB,CAAC;AAKhG,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,OAAO,EACP,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM5D,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,9 @@ export { typescriptQuery } from './query.js';
|
|
|
12
12
|
export { stripStrings, stripComments } from './strip.js';
|
|
13
13
|
export { filterContent } from './filter.js';
|
|
14
14
|
export { discoverTypescriptWorkspaceUnits } from './workspace-units.js';
|
|
15
|
+
// Type-checked Program service (D2): the shared builder of a real ts.Program +
|
|
16
|
+
// bound TypeChecker for type-aware checks. See program-service.ts.
|
|
17
|
+
export { createTypeCheckedProgram, isTypeNullable } from './program-service.js';
|
|
15
18
|
// Function-scope helpers — extracted from `ast-utilities.ts` into a
|
|
16
19
|
// concern-named module. New scope helpers go in `./function-scope.ts`,
|
|
17
20
|
// NOT in `ast-utilities.ts`.
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,8EAA8E;AAC9E,0EAA0E;AAC1E,6EAA6E;AAC7E,oDAAoD;AACpD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,qMAAqM;AACrM,OAAO,EAAE,EAAE,EAAE,CAAC;AAEd,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAExE,oEAAoE;AACpE,uEAAuE;AACvE,6BAA6B;AAC7B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,OAAO,EACP,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAG7B,yEAAyE;AACzE,0EAA0E;AAC1E,4EAA4E;AAC5E,iDAAiD;AACjD,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,8EAA8E;AAC9E,0EAA0E;AAC1E,6EAA6E;AAC7E,oDAAoD;AACpD,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,qMAAqM;AACrM,OAAO,EAAE,EAAE,EAAE,CAAC;AAEd,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAC;AAExE,+EAA+E;AAC/E,mEAAmE;AACnE,OAAO,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGhF,oEAAoE;AACpE,uEAAuE;AACvE,6BAA6B;AAC7B,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,kBAAkB,EAClB,OAAO,EACP,gBAAgB,EAChB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAG7B,yEAAyE;AACzE,0EAA0E;AAC1E,4EAA4E;AAC5E,iDAAiD;AACjD,OAAO,EACL,mBAAmB,EACnB,SAAS,EACT,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,SAAS,EACT,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,WAAW,EACX,uBAAuB,GACxB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Shared TypeScript type-checked Program service.
|
|
3
|
+
*
|
|
4
|
+
* The one canonical place that builds a real `ts.Program` + bound
|
|
5
|
+
* `TypeChecker` over an explicit file set, so type-aware fitness checks can ask
|
|
6
|
+
* the compiler for a value's ACTUAL type instead of guessing from its name.
|
|
7
|
+
* Lives here (per ADR-0010, `@opensip-cli/lang-typescript` is the single TS
|
|
8
|
+
* parse/AST substrate consumed by both fitness checks and the graph adapter) so
|
|
9
|
+
* the dependency on the `typescript` compiler stays isolated to this package —
|
|
10
|
+
* `checks-typescript` already depends on this barrel.
|
|
11
|
+
*
|
|
12
|
+
* This module is STATELESS: it constructs a fresh Program per call. Per-run
|
|
13
|
+
* sharing/caching (build one Program per `fit` run, reused by every type-aware
|
|
14
|
+
* TS check) is the consumer's responsibility (the fitness engine hoists it onto
|
|
15
|
+
* a per-run scope slot) — keeping this layer a pure, testable builder.
|
|
16
|
+
*
|
|
17
|
+
* Cost (measured on a ~900-file first-party corpus, default V8 heap): ~1s
|
|
18
|
+
* cold-start, <0.6 GB RSS (the D2 type-aware-null-safety spec's P0 benchmark).
|
|
19
|
+
*/
|
|
20
|
+
import * as ts from 'typescript';
|
|
21
|
+
/** A built Program with its bound checker and a path-keyed SourceFile lookup. */
|
|
22
|
+
export interface TypeCheckedProgram {
|
|
23
|
+
readonly program: ts.Program;
|
|
24
|
+
readonly checker: ts.TypeChecker;
|
|
25
|
+
/** The tsconfig the Program was anchored to, or `undefined` if none was found. */
|
|
26
|
+
readonly tsconfigPath: string | undefined;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve a SourceFile by absolute path (as passed in `rootFiles`). Declared
|
|
29
|
+
* as a bound property (arrow), not a method, so callers may safely destructure
|
|
30
|
+
* it off the returned object.
|
|
31
|
+
*/
|
|
32
|
+
readonly getSourceFile: (absPath: string) => ts.SourceFile | undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Options for {@link createTypeCheckedProgram}: where to resolve the tsconfig. */
|
|
35
|
+
export interface CreateTypeCheckedProgramOptions {
|
|
36
|
+
/** Directory to resolve a tsconfig from when `tsconfigPath` is not given. */
|
|
37
|
+
readonly projectRoot: string;
|
|
38
|
+
/** Explicit tsconfig path (absolute, or relative to `projectRoot`). */
|
|
39
|
+
readonly tsconfigPath?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Build a type-checked Program over `rootFiles` (absolute on-disk paths). The
|
|
43
|
+
* binder is forced eagerly via `getTypeChecker()` — the dominant cost — so both
|
|
44
|
+
* `node.parent` chains and symbol tables are populated before the caller walks.
|
|
45
|
+
* The Program reads source bytes from disk itself; do NOT pre-transform input.
|
|
46
|
+
*/
|
|
47
|
+
export declare function createTypeCheckedProgram(rootFiles: readonly string[], opts: CreateTypeCheckedProgramOptions): TypeCheckedProgram;
|
|
48
|
+
/**
|
|
49
|
+
* True when `type` CONCRETELY includes `null` or `undefined`. Fail-open by
|
|
50
|
+
* construction: `any`/`unknown`/error/unresolved types have no Null/Undefined
|
|
51
|
+
* union member, so they return `false` — a type-aware nullability check should
|
|
52
|
+
* never flag what the compiler couldn't resolve.
|
|
53
|
+
*/
|
|
54
|
+
export declare function isTypeNullable(type: ts.Type): boolean;
|
|
55
|
+
//# sourceMappingURL=program-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-service.d.ts","sourceRoot":"","sources":["../src/program-service.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC;IAC7B,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC;IACjC,kFAAkF;IAClF,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,aAAa,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,EAAE,CAAC,UAAU,GAAG,SAAS,CAAC;CACxE;AAED,mFAAmF;AACnF,MAAM,WAAW,+BAA+B;IAC9C,6EAA6E;IAC7E,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAqDD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,IAAI,EAAE,+BAA+B,GACpC,kBAAkB,CAsBpB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,GAAG,OAAO,CAGrD"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// @fitness-ignore-file error-handling-quality -- the ParseConfigHost.readFile shim returns undefined when TS asks about a vanished referenced file (TS treats undefined as "skip"); intentional per the ts.ParseConfigHost contract, not a silent error swallow.
|
|
2
|
+
// @fitness-ignore-file unbounded-memory -- readFileSync reads tsconfig.json files only, bounded by the standard TS configuration shape (mirrors graph-typescript/src/discover.ts).
|
|
3
|
+
/**
|
|
4
|
+
* @fileoverview Shared TypeScript type-checked Program service.
|
|
5
|
+
*
|
|
6
|
+
* The one canonical place that builds a real `ts.Program` + bound
|
|
7
|
+
* `TypeChecker` over an explicit file set, so type-aware fitness checks can ask
|
|
8
|
+
* the compiler for a value's ACTUAL type instead of guessing from its name.
|
|
9
|
+
* Lives here (per ADR-0010, `@opensip-cli/lang-typescript` is the single TS
|
|
10
|
+
* parse/AST substrate consumed by both fitness checks and the graph adapter) so
|
|
11
|
+
* the dependency on the `typescript` compiler stays isolated to this package —
|
|
12
|
+
* `checks-typescript` already depends on this barrel.
|
|
13
|
+
*
|
|
14
|
+
* This module is STATELESS: it constructs a fresh Program per call. Per-run
|
|
15
|
+
* sharing/caching (build one Program per `fit` run, reused by every type-aware
|
|
16
|
+
* TS check) is the consumer's responsibility (the fitness engine hoists it onto
|
|
17
|
+
* a per-run scope slot) — keeping this layer a pure, testable builder.
|
|
18
|
+
*
|
|
19
|
+
* Cost (measured on a ~900-file first-party corpus, default V8 heap): ~1s
|
|
20
|
+
* cold-start, <0.6 GB RSS (the D2 type-aware-null-safety spec's P0 benchmark).
|
|
21
|
+
*/
|
|
22
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
23
|
+
import { dirname, isAbsolute, resolve } from 'node:path';
|
|
24
|
+
import * as ts from 'typescript';
|
|
25
|
+
/**
|
|
26
|
+
* Compiler options used when no tsconfig can be found (loose JS/TS checkouts).
|
|
27
|
+
* Conservative and strict-ish so types still resolve; the consumer's fail-open
|
|
28
|
+
* policy (treat unresolved/`any` as non-nullable) covers the weaker signal.
|
|
29
|
+
*/
|
|
30
|
+
const FALLBACK_COMPILER_OPTIONS = {
|
|
31
|
+
target: ts.ScriptTarget.ES2022,
|
|
32
|
+
module: ts.ModuleKind.NodeNext,
|
|
33
|
+
moduleResolution: ts.ModuleResolutionKind.NodeNext,
|
|
34
|
+
strict: true,
|
|
35
|
+
allowJs: true,
|
|
36
|
+
noEmit: true,
|
|
37
|
+
skipLibCheck: true,
|
|
38
|
+
};
|
|
39
|
+
/** Resolve the tsconfig to anchor the Program to, or `undefined` if none. */
|
|
40
|
+
function resolveTsconfigPath(projectRoot, explicit) {
|
|
41
|
+
if (explicit !== undefined) {
|
|
42
|
+
const candidate = isAbsolute(explicit) ? explicit : resolve(projectRoot, explicit);
|
|
43
|
+
return existsSync(candidate) ? candidate : undefined;
|
|
44
|
+
}
|
|
45
|
+
return ts.findConfigFile(projectRoot, (p) => existsSync(p), 'tsconfig.json');
|
|
46
|
+
}
|
|
47
|
+
/** Load + extends-resolve a tsconfig into effective compiler options. */
|
|
48
|
+
function loadCompilerOptions(tsconfigPath) {
|
|
49
|
+
const raw = readFileSync(tsconfigPath, 'utf8');
|
|
50
|
+
const parsed = ts.parseConfigFileTextToJson(tsconfigPath, raw);
|
|
51
|
+
if (parsed.error)
|
|
52
|
+
return { ...FALLBACK_COMPILER_OPTIONS };
|
|
53
|
+
const host = {
|
|
54
|
+
fileExists: (p) => existsSync(p),
|
|
55
|
+
readDirectory: ts.sys.readDirectory.bind(ts.sys),
|
|
56
|
+
readFile: (p) => {
|
|
57
|
+
try {
|
|
58
|
+
return readFileSync(p, 'utf8');
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
useCaseSensitiveFileNames: ts.sys.useCaseSensitiveFileNames,
|
|
65
|
+
};
|
|
66
|
+
const result = ts.parseJsonConfigFileContent(parsed.config, host, dirname(tsconfigPath), {}, tsconfigPath);
|
|
67
|
+
return result.options;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Build a type-checked Program over `rootFiles` (absolute on-disk paths). The
|
|
71
|
+
* binder is forced eagerly via `getTypeChecker()` — the dominant cost — so both
|
|
72
|
+
* `node.parent` chains and symbol tables are populated before the caller walks.
|
|
73
|
+
* The Program reads source bytes from disk itself; do NOT pre-transform input.
|
|
74
|
+
*/
|
|
75
|
+
export function createTypeCheckedProgram(rootFiles, opts) {
|
|
76
|
+
const tsconfigPath = resolveTsconfigPath(opts.projectRoot, opts.tsconfigPath);
|
|
77
|
+
const baseOptions = tsconfigPath
|
|
78
|
+
? loadCompilerOptions(tsconfigPath)
|
|
79
|
+
: { ...FALLBACK_COMPILER_OPTIONS };
|
|
80
|
+
const options = {
|
|
81
|
+
...baseOptions,
|
|
82
|
+
// Anchor to the origin tsconfig for project-reference/rootDir resolution.
|
|
83
|
+
...(tsconfigPath ? { configFilePath: tsconfigPath } : {}),
|
|
84
|
+
noEmit: true,
|
|
85
|
+
};
|
|
86
|
+
const program = ts.createProgram({ rootNames: [...rootFiles], options });
|
|
87
|
+
// Forces the binder (parent pointers + symbol tables). See module header.
|
|
88
|
+
const checker = program.getTypeChecker();
|
|
89
|
+
return {
|
|
90
|
+
program,
|
|
91
|
+
checker,
|
|
92
|
+
tsconfigPath,
|
|
93
|
+
getSourceFile: (absPath) => program.getSourceFile(absPath),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* True when `type` CONCRETELY includes `null` or `undefined`. Fail-open by
|
|
98
|
+
* construction: `any`/`unknown`/error/unresolved types have no Null/Undefined
|
|
99
|
+
* union member, so they return `false` — a type-aware nullability check should
|
|
100
|
+
* never flag what the compiler couldn't resolve.
|
|
101
|
+
*/
|
|
102
|
+
export function isTypeNullable(type) {
|
|
103
|
+
const members = type.isUnion() ? type.types : [type];
|
|
104
|
+
return members.some((m) => (m.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=program-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"program-service.js","sourceRoot":"","sources":["../src/program-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opensip-cli/lang-typescript",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "TypeScript/JavaScript language adapter for opensip-cli",
|
|
6
6
|
"keywords": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"typescript": "~6.0.3",
|
|
38
|
-
"@opensip-cli/core": "0.1.
|
|
38
|
+
"@opensip-cli/core": "0.1.8"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "^24.13.2",
|