jsii 5.9.9 → 5.9.11-dev.0
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/SUPPORT.md +12 -12
- package/lib/assembler.js +11 -1
- package/lib/assembler.js.map +1 -1
- package/lib/helpers.js +1 -1
- package/lib/helpers.js.map +1 -1
- package/lib/type-analysis.d.ts +11 -0
- package/lib/type-analysis.js +123 -0
- package/lib/type-analysis.js.map +1 -0
- package/lib/type-reference.d.ts +10 -0
- package/lib/type-reference.js +23 -0
- package/lib/type-reference.js.map +1 -1
- package/lib/validator.d.ts +6 -2
- package/lib/validator.js +62 -34
- package/lib/validator.js.map +1 -1
- package/lib/version.d.ts +2 -2
- package/lib/version.js +2 -2
- package/lib/version.js.map +1 -1
- package/package.json +1 -1
package/lib/helpers.js
CHANGED
|
@@ -22,7 +22,7 @@ const utils_1 = require("./utils");
|
|
|
22
22
|
/**
|
|
23
23
|
* Assembly features supported by this compiler
|
|
24
24
|
*/
|
|
25
|
-
exports.ASSEMBLY_FEATURES_SUPPORTED = ['intersection-types'];
|
|
25
|
+
exports.ASSEMBLY_FEATURES_SUPPORTED = ['intersection-types', 'class-covariant-overrides'];
|
|
26
26
|
/**
|
|
27
27
|
* Compile a piece of source and return the JSII assembly for it
|
|
28
28
|
*
|
package/lib/helpers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Helper routines for use with the jsii compiler\n *\n * These are mostly used for testing, but all projects that need to exercise\n * the JSII compiler to test something need to share this code, so might as\n * well put it in one reusable place.\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { PackageJson, loadAssemblyFromPath, writeAssembly } from '@jsii/spec';\nimport * as spec from '@jsii/spec';\nimport { Diagnostic, DiagnosticCategory } from 'typescript';\n\nimport { Compiler, CompilerOptions } from './compiler';\nimport { loadProjectInfo, ProjectInfo } from './project-info';\nimport { formatDiagnostic, JsiiError } from './utils';\n\n/**\n * A set of source files for `sourceToAssemblyHelper`, at least containing 'index.ts'\n */\nexport type MultipleSourceFiles = {\n 'index.ts': string;\n [name: string]: string;\n};\n\n/**\n * Assembly features supported by this compiler\n */\nexport const ASSEMBLY_FEATURES_SUPPORTED: spec.JsiiFeature[] = ['intersection-types'];\n\n/**\n * Compile a piece of source and return the JSII assembly for it\n *\n * Only usable for trivial cases and tests.\n *\n * @param source can either be a single `string` (the content of `index.ts`), or\n * a map of fileName to content, which *must* include `index.ts`.\n * @param options accepts a callback for historical reasons but really expects to\n * take an options object.\n */\nexport function sourceToAssemblyHelper(\n source: string | MultipleSourceFiles,\n options?: TestCompilationOptions | ((obj: PackageJson) => void),\n): spec.Assembly {\n const result = compileJsiiForTest(source, options);\n if (result.type !== 'success') {\n throw new Error('Compilation failed');\n }\n return result.assembly;\n}\n\nexport type HelperCompilationOut = HelperCompilationResult | HelperCompilationFailure;\n\n/**\n * Successful output of a compilation command (for testing)\n *\n * A better name would have been `HelperCompilationSuccess`, but the name is part of\n * the public API surface, so we keep it like this.\n */\nexport interface HelperCompilationResult {\n readonly type: 'success';\n\n /**\n * The generated assembly\n */\n readonly assembly: spec.Assembly;\n\n /**\n * Generated .js/.d.ts file(s)\n */\n readonly files: Record<string, string>;\n\n /**\n * The packageInfo used\n */\n readonly packageJson: PackageJson;\n\n /**\n * Whether to compress the assembly file\n */\n readonly compressAssembly: boolean;\n\n /**\n * Diagnostics that occurred during compilation\n */\n readonly diagnostics: readonly Diagnostic[];\n}\n\nexport interface HelperCompilationFailure {\n readonly type: 'failure';\n\n /**\n * Diagnostics that occurred during compilation\n *\n * Contains at least one error.\n */\n readonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * Compile a piece of source and return the assembly and compiled sources for it\n *\n * Only usable for trivial cases and tests.\n *\n * @param source can either be a single `string` (the content of `index.ts`), or\n * a map of fileName to content, which *must* include `index.ts`.\n * @param options accepts a callback for historical reasons but really expects to\n * take an options object.\n */\nexport function compileJsiiForTest<O extends TestCompilationOptions>(\n source: string | { 'index.ts': string; [name: string]: string },\n options?: O | ((obj: PackageJson) => void),\n compilerOptions?: Omit<CompilerOptions, 'projectInfo' | 'watch'>,\n): ResultOrSuccess<O> {\n if (typeof source === 'string') {\n source = { 'index.ts': source };\n }\n\n const inSomeLocation =\n isOptionsObject(options) && options.compilationDirectory ? inOtherDir(options.compilationDirectory) : inTempDir;\n\n // Easiest way to get the source into the compiler is to write it to disk somewhere.\n // I guess we could make an in-memory compiler host but that seems like work...\n return inSomeLocation(() => {\n for (const [fileName, content] of Object.entries(source)) {\n fs.mkdirSync(path.dirname(fileName), { recursive: true });\n fs.writeFileSync(fileName, content, { encoding: 'utf-8' });\n }\n const { projectInfo, packageJson } = makeProjectInfo(\n 'index.ts',\n typeof options === 'function'\n ? options\n : (pi) => {\n Object.assign(pi, options?.packageJson ?? options?.projectInfo ?? {});\n },\n );\n const compiler = new Compiler({\n projectInfo,\n ...compilerOptions,\n });\n const emitResult = compiler.emit();\n\n const errors = emitResult.diagnostics.filter((d) => d.category === DiagnosticCategory.Error);\n\n if (typeof options !== 'object' || !options?.captureDiagnostics) {\n for (const error of errors) {\n console.error(formatDiagnostic(error, projectInfo.projectRoot));\n // logDiagnostic() doesn't work out of the box, so console.error() it is.\n }\n }\n\n if (errors.length > 0 || emitResult.emitSkipped) {\n if (typeof options === 'object' && options?.captureDiagnostics) {\n return {\n type: 'failure',\n diagnostics: emitResult.diagnostics,\n } satisfies HelperCompilationFailure;\n }\n throw new JsiiError('There were compiler errors');\n }\n\n const assembly = loadAssemblyFromPath(process.cwd(), false, ASSEMBLY_FEATURES_SUPPORTED);\n const files: Record<string, string> = {};\n\n for (const filename of Object.keys(source)) {\n let jsFile = filename.replace(/\\.ts$/, '.js');\n let dtsFile = filename.replace(/\\.ts$/, '.d.ts');\n if (projectInfo.tsc?.outDir && filename !== 'README.md') {\n jsFile = path.join(projectInfo.tsc.outDir, jsFile);\n dtsFile = path.join(projectInfo.tsc.outDir, dtsFile);\n }\n\n // eslint-disable-next-line no-await-in-loop\n files[jsFile] = fs.readFileSync(jsFile, { encoding: 'utf-8' });\n // eslint-disable-next-line no-await-in-loop\n files[dtsFile] = fs.readFileSync(dtsFile, { encoding: 'utf-8' });\n\n const warningsFileName = '.warnings.jsii.js';\n if (fs.existsSync(warningsFileName)) {\n // eslint-disable-next-line no-await-in-loop\n files[warningsFileName] = fs.readFileSync(warningsFileName, {\n encoding: 'utf-8',\n });\n }\n }\n\n return {\n type: 'success',\n assembly,\n files,\n packageJson,\n compressAssembly: isOptionsObject(options) && options.compressAssembly ? true : false,\n diagnostics: emitResult.diagnostics,\n } satisfies HelperCompilationResult;\n }) as ResultOrSuccess<O>;\n}\n\ntype ResultOrSuccess<O extends TestCompilationOptions> = O['captureDiagnostics'] extends true\n ? HelperCompilationOut\n : HelperCompilationResult;\n\nfunction inTempDir<T>(block: () => T): T {\n const origDir = process.cwd();\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii'));\n process.chdir(tmpDir);\n const ret = block();\n process.chdir(origDir);\n fs.rmSync(tmpDir, { force: true, recursive: true });\n return ret;\n}\n\nfunction inOtherDir(dir: string) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint\n return <T extends unknown>(block: () => T): T => {\n const origDir = process.cwd();\n process.chdir(dir);\n try {\n return block();\n } finally {\n process.chdir(origDir);\n }\n };\n}\n\n/**\n * Obtain project info so we can call the compiler\n *\n * Creating this directly in-memory leads to slightly different behavior from calling\n * jsii from the command-line, and I don't want to figure out right now.\n *\n * Most consistent behavior seems to be to write a package.json to disk and\n * then calling the same functions as the CLI would.\n */\nfunction makeProjectInfo(\n types: string,\n cb?: (obj: PackageJson) => void,\n): { projectInfo: ProjectInfo; packageJson: PackageJson } {\n const packageJson: PackageJson = {\n types,\n main: types.replace(/(?:\\.d)?\\.ts(x?)/, '.js$1'),\n name: 'testpkg', // That's what package.json would tell if we look up...\n version: '0.0.1',\n license: 'Apache-2.0',\n author: { name: 'John Doe' },\n repository: { type: 'git', url: 'https://github.com/aws/jsii.git' },\n jsii: {},\n };\n\n if (cb) {\n cb(packageJson);\n }\n\n fs.writeFileSync(\n 'package.json',\n JSON.stringify(packageJson, (_: string, v: any) => v, 2),\n 'utf-8',\n );\n\n const { projectInfo } = loadProjectInfo(path.resolve(process.cwd(), '.'));\n return { projectInfo, packageJson };\n}\n\nexport interface TestCompilationOptions {\n /**\n * The directory in which we write and compile the files\n */\n readonly compilationDirectory?: string;\n\n /**\n * Parts of projectInfo to override (package name etc)\n *\n * @deprecated Prefer using `packageJson` instead.\n */\n readonly projectInfo?: Partial<PackageJson>;\n\n /**\n * Parts of projectInfo to override (package name etc)\n *\n * @default - Use some default values\n */\n readonly packageJson?: Partial<PackageJson>;\n\n /**\n * Whether to compress the assembly file.\n *\n * @default false\n */\n readonly compressAssembly?: boolean;\n\n /**\n * Whether or not to print the diagnostics\n *\n * @default false\n */\n readonly captureDiagnostics?: boolean;\n}\n\nfunction isOptionsObject(\n x: TestCompilationOptions | ((obj: PackageJson) => void) | undefined,\n): x is TestCompilationOptions {\n return x ? typeof x === 'object' : false;\n}\n\n/**\n * An NPM-ready workspace where we can install test-compile dependencies and compile new assemblies\n */\nexport class TestWorkspace {\n /**\n * Create a new workspace.\n *\n * Creates a temporary directory, don't forget to call cleanUp\n */\n public static create(): TestWorkspace {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii-testworkspace'));\n fs.mkdirSync(tmpDir, { recursive: true });\n return new TestWorkspace(tmpDir);\n }\n\n /**\n * Execute a block with a temporary workspace\n */\n public static withWorkspace<A>(block: (ws: TestWorkspace) => A): A {\n const ws = TestWorkspace.create();\n try {\n return block(ws);\n } finally {\n ws.cleanup();\n }\n }\n\n private readonly installed = new Set<string>();\n\n private constructor(public readonly rootDirectory: string) {}\n\n /**\n * Add a test-compiled jsii assembly as a dependency\n */\n public addDependency(dependencyAssembly: HelperCompilationOut) {\n if (dependencyAssembly.type !== 'success') {\n throw new JsiiError('Cannot add dependency: assembly compilation failed');\n }\n\n if (this.installed.has(dependencyAssembly.assembly.name)) {\n throw new JsiiError(\n `A dependency with name '${dependencyAssembly.assembly.name}' was already installed. Give one a different name.`,\n );\n }\n this.installed.add(dependencyAssembly.assembly.name);\n\n // The following is silly, however: the helper has compiled the given source to\n // an assembly, and output files, and then removed their traces from disk.\n // We need those files back on disk, so write them back out again.\n //\n // We will drop them in 'node_modules/<name>' so they can be imported\n // as if they were installed.\n const modDir = path.join(this.rootDirectory, 'node_modules', dependencyAssembly.assembly.name);\n fs.mkdirSync(modDir, { recursive: true });\n\n writeAssembly(modDir, dependencyAssembly.assembly, {\n compress: dependencyAssembly.compressAssembly,\n });\n fs.writeFileSync(\n path.join(modDir, 'package.json'),\n JSON.stringify(dependencyAssembly.packageJson, null, 2),\n 'utf-8',\n );\n\n for (const [fileName, fileContents] of Object.entries(dependencyAssembly.files)) {\n fs.mkdirSync(path.dirname(path.join(modDir, fileName)), {\n recursive: true,\n });\n fs.writeFileSync(path.join(modDir, fileName), fileContents);\n }\n }\n\n public dependencyDir(name: string) {\n if (!this.installed.has(name)) {\n throw new JsiiError(`No dependency with name '${name}' has been installed`);\n }\n return path.join(this.rootDirectory, 'node_modules', name);\n }\n\n public cleanup() {\n fs.rmSync(this.rootDirectory, { force: true, recursive: true });\n }\n}\n\n// Alias for backwards compatibility\nexport type PackageInfo = PackageJson;\n\n/**\n * TSConfig paths can either be relative to the project or absolute.\n * This function normalizes paths to be relative to the provided root.\n * After normalization, code using these paths can be much simpler.\n *\n * @param root the project root\n * @param pathToNormalize the path to normalize, might be empty\n */\nexport function normalizeConfigPath(root: string, pathToNormalize?: string): string | undefined {\n if (pathToNormalize == null || !path.isAbsolute(pathToNormalize)) {\n return pathToNormalize;\n }\n return path.relative(root, pathToNormalize);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../src/helpers.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Helper routines for use with the jsii compiler\n *\n * These are mostly used for testing, but all projects that need to exercise\n * the JSII compiler to test something need to share this code, so might as\n * well put it in one reusable place.\n */\n\nimport * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { PackageJson, loadAssemblyFromPath, writeAssembly } from '@jsii/spec';\nimport * as spec from '@jsii/spec';\nimport { Diagnostic, DiagnosticCategory } from 'typescript';\n\nimport { Compiler, CompilerOptions } from './compiler';\nimport { loadProjectInfo, ProjectInfo } from './project-info';\nimport { formatDiagnostic, JsiiError } from './utils';\n\n/**\n * A set of source files for `sourceToAssemblyHelper`, at least containing 'index.ts'\n */\nexport type MultipleSourceFiles = {\n 'index.ts': string;\n [name: string]: string;\n};\n\n/**\n * Assembly features supported by this compiler\n */\nexport const ASSEMBLY_FEATURES_SUPPORTED: spec.JsiiFeature[] = ['intersection-types', 'class-covariant-overrides'];\n\n/**\n * Compile a piece of source and return the JSII assembly for it\n *\n * Only usable for trivial cases and tests.\n *\n * @param source can either be a single `string` (the content of `index.ts`), or\n * a map of fileName to content, which *must* include `index.ts`.\n * @param options accepts a callback for historical reasons but really expects to\n * take an options object.\n */\nexport function sourceToAssemblyHelper(\n source: string | MultipleSourceFiles,\n options?: TestCompilationOptions | ((obj: PackageJson) => void),\n): spec.Assembly {\n const result = compileJsiiForTest(source, options);\n if (result.type !== 'success') {\n throw new Error('Compilation failed');\n }\n return result.assembly;\n}\n\nexport type HelperCompilationOut = HelperCompilationResult | HelperCompilationFailure;\n\n/**\n * Successful output of a compilation command (for testing)\n *\n * A better name would have been `HelperCompilationSuccess`, but the name is part of\n * the public API surface, so we keep it like this.\n */\nexport interface HelperCompilationResult {\n readonly type: 'success';\n\n /**\n * The generated assembly\n */\n readonly assembly: spec.Assembly;\n\n /**\n * Generated .js/.d.ts file(s)\n */\n readonly files: Record<string, string>;\n\n /**\n * The packageInfo used\n */\n readonly packageJson: PackageJson;\n\n /**\n * Whether to compress the assembly file\n */\n readonly compressAssembly: boolean;\n\n /**\n * Diagnostics that occurred during compilation\n */\n readonly diagnostics: readonly Diagnostic[];\n}\n\nexport interface HelperCompilationFailure {\n readonly type: 'failure';\n\n /**\n * Diagnostics that occurred during compilation\n *\n * Contains at least one error.\n */\n readonly diagnostics: readonly Diagnostic[];\n}\n\n/**\n * Compile a piece of source and return the assembly and compiled sources for it\n *\n * Only usable for trivial cases and tests.\n *\n * @param source can either be a single `string` (the content of `index.ts`), or\n * a map of fileName to content, which *must* include `index.ts`.\n * @param options accepts a callback for historical reasons but really expects to\n * take an options object.\n */\nexport function compileJsiiForTest<O extends TestCompilationOptions>(\n source: string | { 'index.ts': string; [name: string]: string },\n options?: O | ((obj: PackageJson) => void),\n compilerOptions?: Omit<CompilerOptions, 'projectInfo' | 'watch'>,\n): ResultOrSuccess<O> {\n if (typeof source === 'string') {\n source = { 'index.ts': source };\n }\n\n const inSomeLocation =\n isOptionsObject(options) && options.compilationDirectory ? inOtherDir(options.compilationDirectory) : inTempDir;\n\n // Easiest way to get the source into the compiler is to write it to disk somewhere.\n // I guess we could make an in-memory compiler host but that seems like work...\n return inSomeLocation(() => {\n for (const [fileName, content] of Object.entries(source)) {\n fs.mkdirSync(path.dirname(fileName), { recursive: true });\n fs.writeFileSync(fileName, content, { encoding: 'utf-8' });\n }\n const { projectInfo, packageJson } = makeProjectInfo(\n 'index.ts',\n typeof options === 'function'\n ? options\n : (pi) => {\n Object.assign(pi, options?.packageJson ?? options?.projectInfo ?? {});\n },\n );\n const compiler = new Compiler({\n projectInfo,\n ...compilerOptions,\n });\n const emitResult = compiler.emit();\n\n const errors = emitResult.diagnostics.filter((d) => d.category === DiagnosticCategory.Error);\n\n if (typeof options !== 'object' || !options?.captureDiagnostics) {\n for (const error of errors) {\n console.error(formatDiagnostic(error, projectInfo.projectRoot));\n // logDiagnostic() doesn't work out of the box, so console.error() it is.\n }\n }\n\n if (errors.length > 0 || emitResult.emitSkipped) {\n if (typeof options === 'object' && options?.captureDiagnostics) {\n return {\n type: 'failure',\n diagnostics: emitResult.diagnostics,\n } satisfies HelperCompilationFailure;\n }\n throw new JsiiError('There were compiler errors');\n }\n\n const assembly = loadAssemblyFromPath(process.cwd(), false, ASSEMBLY_FEATURES_SUPPORTED);\n const files: Record<string, string> = {};\n\n for (const filename of Object.keys(source)) {\n let jsFile = filename.replace(/\\.ts$/, '.js');\n let dtsFile = filename.replace(/\\.ts$/, '.d.ts');\n if (projectInfo.tsc?.outDir && filename !== 'README.md') {\n jsFile = path.join(projectInfo.tsc.outDir, jsFile);\n dtsFile = path.join(projectInfo.tsc.outDir, dtsFile);\n }\n\n // eslint-disable-next-line no-await-in-loop\n files[jsFile] = fs.readFileSync(jsFile, { encoding: 'utf-8' });\n // eslint-disable-next-line no-await-in-loop\n files[dtsFile] = fs.readFileSync(dtsFile, { encoding: 'utf-8' });\n\n const warningsFileName = '.warnings.jsii.js';\n if (fs.existsSync(warningsFileName)) {\n // eslint-disable-next-line no-await-in-loop\n files[warningsFileName] = fs.readFileSync(warningsFileName, {\n encoding: 'utf-8',\n });\n }\n }\n\n return {\n type: 'success',\n assembly,\n files,\n packageJson,\n compressAssembly: isOptionsObject(options) && options.compressAssembly ? true : false,\n diagnostics: emitResult.diagnostics,\n } satisfies HelperCompilationResult;\n }) as ResultOrSuccess<O>;\n}\n\ntype ResultOrSuccess<O extends TestCompilationOptions> = O['captureDiagnostics'] extends true\n ? HelperCompilationOut\n : HelperCompilationResult;\n\nfunction inTempDir<T>(block: () => T): T {\n const origDir = process.cwd();\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii'));\n process.chdir(tmpDir);\n const ret = block();\n process.chdir(origDir);\n fs.rmSync(tmpDir, { force: true, recursive: true });\n return ret;\n}\n\nfunction inOtherDir(dir: string) {\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-constraint\n return <T extends unknown>(block: () => T): T => {\n const origDir = process.cwd();\n process.chdir(dir);\n try {\n return block();\n } finally {\n process.chdir(origDir);\n }\n };\n}\n\n/**\n * Obtain project info so we can call the compiler\n *\n * Creating this directly in-memory leads to slightly different behavior from calling\n * jsii from the command-line, and I don't want to figure out right now.\n *\n * Most consistent behavior seems to be to write a package.json to disk and\n * then calling the same functions as the CLI would.\n */\nfunction makeProjectInfo(\n types: string,\n cb?: (obj: PackageJson) => void,\n): { projectInfo: ProjectInfo; packageJson: PackageJson } {\n const packageJson: PackageJson = {\n types,\n main: types.replace(/(?:\\.d)?\\.ts(x?)/, '.js$1'),\n name: 'testpkg', // That's what package.json would tell if we look up...\n version: '0.0.1',\n license: 'Apache-2.0',\n author: { name: 'John Doe' },\n repository: { type: 'git', url: 'https://github.com/aws/jsii.git' },\n jsii: {},\n };\n\n if (cb) {\n cb(packageJson);\n }\n\n fs.writeFileSync(\n 'package.json',\n JSON.stringify(packageJson, (_: string, v: any) => v, 2),\n 'utf-8',\n );\n\n const { projectInfo } = loadProjectInfo(path.resolve(process.cwd(), '.'));\n return { projectInfo, packageJson };\n}\n\nexport interface TestCompilationOptions {\n /**\n * The directory in which we write and compile the files\n */\n readonly compilationDirectory?: string;\n\n /**\n * Parts of projectInfo to override (package name etc)\n *\n * @deprecated Prefer using `packageJson` instead.\n */\n readonly projectInfo?: Partial<PackageJson>;\n\n /**\n * Parts of projectInfo to override (package name etc)\n *\n * @default - Use some default values\n */\n readonly packageJson?: Partial<PackageJson>;\n\n /**\n * Whether to compress the assembly file.\n *\n * @default false\n */\n readonly compressAssembly?: boolean;\n\n /**\n * Whether or not to print the diagnostics\n *\n * @default false\n */\n readonly captureDiagnostics?: boolean;\n}\n\nfunction isOptionsObject(\n x: TestCompilationOptions | ((obj: PackageJson) => void) | undefined,\n): x is TestCompilationOptions {\n return x ? typeof x === 'object' : false;\n}\n\n/**\n * An NPM-ready workspace where we can install test-compile dependencies and compile new assemblies\n */\nexport class TestWorkspace {\n /**\n * Create a new workspace.\n *\n * Creates a temporary directory, don't forget to call cleanUp\n */\n public static create(): TestWorkspace {\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'jsii-testworkspace'));\n fs.mkdirSync(tmpDir, { recursive: true });\n return new TestWorkspace(tmpDir);\n }\n\n /**\n * Execute a block with a temporary workspace\n */\n public static withWorkspace<A>(block: (ws: TestWorkspace) => A): A {\n const ws = TestWorkspace.create();\n try {\n return block(ws);\n } finally {\n ws.cleanup();\n }\n }\n\n private readonly installed = new Set<string>();\n\n private constructor(public readonly rootDirectory: string) {}\n\n /**\n * Add a test-compiled jsii assembly as a dependency\n */\n public addDependency(dependencyAssembly: HelperCompilationOut) {\n if (dependencyAssembly.type !== 'success') {\n throw new JsiiError('Cannot add dependency: assembly compilation failed');\n }\n\n if (this.installed.has(dependencyAssembly.assembly.name)) {\n throw new JsiiError(\n `A dependency with name '${dependencyAssembly.assembly.name}' was already installed. Give one a different name.`,\n );\n }\n this.installed.add(dependencyAssembly.assembly.name);\n\n // The following is silly, however: the helper has compiled the given source to\n // an assembly, and output files, and then removed their traces from disk.\n // We need those files back on disk, so write them back out again.\n //\n // We will drop them in 'node_modules/<name>' so they can be imported\n // as if they were installed.\n const modDir = path.join(this.rootDirectory, 'node_modules', dependencyAssembly.assembly.name);\n fs.mkdirSync(modDir, { recursive: true });\n\n writeAssembly(modDir, dependencyAssembly.assembly, {\n compress: dependencyAssembly.compressAssembly,\n });\n fs.writeFileSync(\n path.join(modDir, 'package.json'),\n JSON.stringify(dependencyAssembly.packageJson, null, 2),\n 'utf-8',\n );\n\n for (const [fileName, fileContents] of Object.entries(dependencyAssembly.files)) {\n fs.mkdirSync(path.dirname(path.join(modDir, fileName)), {\n recursive: true,\n });\n fs.writeFileSync(path.join(modDir, fileName), fileContents);\n }\n }\n\n public dependencyDir(name: string) {\n if (!this.installed.has(name)) {\n throw new JsiiError(`No dependency with name '${name}' has been installed`);\n }\n return path.join(this.rootDirectory, 'node_modules', name);\n }\n\n public cleanup() {\n fs.rmSync(this.rootDirectory, { force: true, recursive: true });\n }\n}\n\n// Alias for backwards compatibility\nexport type PackageInfo = PackageJson;\n\n/**\n * TSConfig paths can either be relative to the project or absolute.\n * This function normalizes paths to be relative to the provided root.\n * After normalization, code using these paths can be much simpler.\n *\n * @param root the project root\n * @param pathToNormalize the path to normalize, might be empty\n */\nexport function normalizeConfigPath(root: string, pathToNormalize?: string): string | undefined {\n if (pathToNormalize == null || !path.isAbsolute(pathToNormalize)) {\n return pathToNormalize;\n }\n return path.relative(root, pathToNormalize);\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as spec from '@jsii/spec';
|
|
2
|
+
import { TypeResolver } from './type-reference';
|
|
3
|
+
/**
|
|
4
|
+
* Check if subType is an allowed covariant subtype to superType
|
|
5
|
+
*
|
|
6
|
+
* This is not a generic check for subtypes or covariance, but a specific implementation
|
|
7
|
+
* that checks the currently allowed conditions for class covariance.
|
|
8
|
+
* In practice, this is driven by C# limitations.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isAllowedCovariantSubtype(subType: spec.TypeReference | undefined, superType: spec.TypeReference | undefined, dereference: TypeResolver): boolean;
|
|
11
|
+
//# sourceMappingURL=type-analysis.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isAllowedCovariantSubtype = isAllowedCovariantSubtype;
|
|
4
|
+
const spec = require("@jsii/spec");
|
|
5
|
+
const deepEqual = require("fast-deep-equal");
|
|
6
|
+
/**
|
|
7
|
+
* Check if subType is an allowed covariant subtype to superType
|
|
8
|
+
*
|
|
9
|
+
* This is not a generic check for subtypes or covariance, but a specific implementation
|
|
10
|
+
* that checks the currently allowed conditions for class covariance.
|
|
11
|
+
* In practice, this is driven by C# limitations.
|
|
12
|
+
*/
|
|
13
|
+
function isAllowedCovariantSubtype(subType, superType, dereference) {
|
|
14
|
+
// one void, while other isn't => not covariant
|
|
15
|
+
if ((subType === undefined) !== (superType === undefined)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
// Same type is always covariant
|
|
19
|
+
if (deepEqual(subType, superType)) {
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
// Handle array collections (covariant)
|
|
23
|
+
if (spec.isCollectionTypeReference(subType) && spec.isCollectionTypeReference(superType)) {
|
|
24
|
+
if (subType.collection.kind === 'array' && superType.collection.kind === 'array') {
|
|
25
|
+
return isAllowedCovariantSubtype(subType.collection.elementtype, superType.collection.elementtype, dereference);
|
|
26
|
+
}
|
|
27
|
+
// Maps are not allowed to be covariant in C#, so we exclude them here.
|
|
28
|
+
// This seems to be because we use C# Dictionary to implements Maps, which are using generics and generics are not allowed to be covariant
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
// Union types are currently not allowed, because we have not seen the need for it.
|
|
32
|
+
// Technically narrowing (removing `| Type` or subtyping) could be allowed and this works in C#.
|
|
33
|
+
if (spec.isUnionTypeReference(subType) || spec.isUnionTypeReference(superType)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Intersection types are invalid, because intersections are only allowed as inputs
|
|
37
|
+
// and covariance is only allowed in outputs.
|
|
38
|
+
if (spec.isIntersectionTypeReference(subType) || spec.isIntersectionTypeReference(superType)) {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
// Primitives can never be covariant to each other in C#
|
|
42
|
+
if (spec.isPrimitiveTypeReference(subType) || spec.isPrimitiveTypeReference(superType)) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
// We really only support covariance for named types (and lists of named types).
|
|
46
|
+
// To be safe, let's guard against any unknown cases.
|
|
47
|
+
if (!spec.isNamedTypeReference(subType) || !spec.isNamedTypeReference(superType)) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const subTypeSpec = dereference(subType.fqn);
|
|
51
|
+
const superTypeSpec = dereference(superType.fqn);
|
|
52
|
+
if (!subTypeSpec || !superTypeSpec) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
// Handle class-to-class inheritance
|
|
56
|
+
if (spec.isClassType(subTypeSpec) && spec.isClassType(superTypeSpec)) {
|
|
57
|
+
return _classExtendsClass(subTypeSpec, superType.fqn);
|
|
58
|
+
}
|
|
59
|
+
// Handle interface-to-interface inheritance
|
|
60
|
+
if (spec.isInterfaceType(subTypeSpec) && spec.isInterfaceType(superTypeSpec)) {
|
|
61
|
+
return _interfaceExtendsInterface(subTypeSpec, superType.fqn);
|
|
62
|
+
}
|
|
63
|
+
// Handle class implementing interface
|
|
64
|
+
if (spec.isClassType(subTypeSpec) && spec.isInterfaceType(superTypeSpec)) {
|
|
65
|
+
return _classImplementsInterface(subTypeSpec, superType.fqn);
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
function _classExtendsClass(classType, targetFqn) {
|
|
69
|
+
let current = classType;
|
|
70
|
+
while (current.base) {
|
|
71
|
+
if (current.base === targetFqn) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
const baseType = dereference(current.base);
|
|
75
|
+
if (!spec.isClassType(baseType)) {
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
current = baseType;
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
function _classImplementsInterface(classType, interfaceFqn) {
|
|
83
|
+
// Check direct interfaces
|
|
84
|
+
if (classType.interfaces?.includes(interfaceFqn)) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
// Check inherited interfaces
|
|
88
|
+
if (classType.interfaces) {
|
|
89
|
+
for (const iface of classType.interfaces) {
|
|
90
|
+
const ifaceType = dereference(iface);
|
|
91
|
+
if (spec.isInterfaceType(ifaceType) && _interfaceExtendsInterface(ifaceType, interfaceFqn)) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Check base class interfaces
|
|
97
|
+
if (classType.base) {
|
|
98
|
+
const baseType = dereference(classType.base);
|
|
99
|
+
if (spec.isClassType(baseType)) {
|
|
100
|
+
return _classImplementsInterface(baseType, interfaceFqn);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
function _interfaceExtendsInterface(interfaceType, targetFqn) {
|
|
106
|
+
if (interfaceType.fqn === targetFqn) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
if (interfaceType.interfaces) {
|
|
110
|
+
for (const iface of interfaceType.interfaces) {
|
|
111
|
+
if (iface === targetFqn) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
const ifaceType = dereference(iface);
|
|
115
|
+
if (spec.isInterfaceType(ifaceType) && _interfaceExtendsInterface(ifaceType, targetFqn)) {
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=type-analysis.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-analysis.js","sourceRoot":"","sources":["../src/type-analysis.ts"],"names":[],"mappings":"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","sourcesContent":["import * as spec from '@jsii/spec';\nimport * as deepEqual from 'fast-deep-equal';\nimport { TypeResolver } from './type-reference';\n\n/**\n * Check if subType is an allowed covariant subtype to superType\n *\n * This is not a generic check for subtypes or covariance, but a specific implementation\n * that checks the currently allowed conditions for class covariance.\n * In practice, this is driven by C# limitations.\n */\nexport function isAllowedCovariantSubtype(\n subType: spec.TypeReference | undefined,\n superType: spec.TypeReference | undefined,\n dereference: TypeResolver,\n): boolean {\n // one void, while other isn't => not covariant\n if ((subType === undefined) !== (superType === undefined)) {\n return false;\n }\n\n // Same type is always covariant\n if (deepEqual(subType, superType)) {\n return true;\n }\n\n // Handle array collections (covariant)\n if (spec.isCollectionTypeReference(subType) && spec.isCollectionTypeReference(superType)) {\n if (subType.collection.kind === 'array' && superType.collection.kind === 'array') {\n return isAllowedCovariantSubtype(subType.collection.elementtype, superType.collection.elementtype, dereference);\n }\n // Maps are not allowed to be covariant in C#, so we exclude them here.\n // This seems to be because we use C# Dictionary to implements Maps, which are using generics and generics are not allowed to be covariant\n return false;\n }\n\n // Union types are currently not allowed, because we have not seen the need for it.\n // Technically narrowing (removing `| Type` or subtyping) could be allowed and this works in C#.\n if (spec.isUnionTypeReference(subType) || spec.isUnionTypeReference(superType)) {\n return false;\n }\n\n // Intersection types are invalid, because intersections are only allowed as inputs\n // and covariance is only allowed in outputs.\n if (spec.isIntersectionTypeReference(subType) || spec.isIntersectionTypeReference(superType)) {\n return false;\n }\n\n // Primitives can never be covariant to each other in C#\n if (spec.isPrimitiveTypeReference(subType) || spec.isPrimitiveTypeReference(superType)) {\n return false;\n }\n\n // We really only support covariance for named types (and lists of named types).\n // To be safe, let's guard against any unknown cases.\n if (!spec.isNamedTypeReference(subType) || !spec.isNamedTypeReference(superType)) {\n return false;\n }\n\n const subTypeSpec = dereference(subType.fqn);\n const superTypeSpec = dereference(superType.fqn);\n\n if (!subTypeSpec || !superTypeSpec) {\n return false;\n }\n\n // Handle class-to-class inheritance\n if (spec.isClassType(subTypeSpec) && spec.isClassType(superTypeSpec)) {\n return _classExtendsClass(subTypeSpec, superType.fqn);\n }\n\n // Handle interface-to-interface inheritance\n if (spec.isInterfaceType(subTypeSpec) && spec.isInterfaceType(superTypeSpec)) {\n return _interfaceExtendsInterface(subTypeSpec, superType.fqn);\n }\n\n // Handle class implementing interface\n if (spec.isClassType(subTypeSpec) && spec.isInterfaceType(superTypeSpec)) {\n return _classImplementsInterface(subTypeSpec, superType.fqn);\n }\n\n return false;\n\n function _classExtendsClass(classType: spec.ClassType, targetFqn: string): boolean {\n let current = classType;\n while (current.base) {\n if (current.base === targetFqn) {\n return true;\n }\n const baseType = dereference(current.base);\n if (!spec.isClassType(baseType)) {\n break;\n }\n current = baseType;\n }\n return false;\n }\n\n function _classImplementsInterface(classType: spec.ClassType, interfaceFqn: string): boolean {\n // Check direct interfaces\n if (classType.interfaces?.includes(interfaceFqn)) {\n return true;\n }\n\n // Check inherited interfaces\n if (classType.interfaces) {\n for (const iface of classType.interfaces) {\n const ifaceType = dereference(iface);\n if (spec.isInterfaceType(ifaceType) && _interfaceExtendsInterface(ifaceType, interfaceFqn)) {\n return true;\n }\n }\n }\n\n // Check base class interfaces\n if (classType.base) {\n const baseType = dereference(classType.base);\n if (spec.isClassType(baseType)) {\n return _classImplementsInterface(baseType, interfaceFqn);\n }\n }\n\n return false;\n }\n\n function _interfaceExtendsInterface(interfaceType: spec.InterfaceType, targetFqn: string): boolean {\n if (interfaceType.fqn === targetFqn) {\n return true;\n }\n\n if (interfaceType.interfaces) {\n for (const iface of interfaceType.interfaces) {\n if (iface === targetFqn) {\n return true;\n }\n const ifaceType = dereference(iface);\n if (spec.isInterfaceType(ifaceType) && _interfaceExtendsInterface(ifaceType, targetFqn)) {\n return true;\n }\n }\n }\n\n return false;\n }\n}\n"]}
|
package/lib/type-reference.d.ts
CHANGED
|
@@ -7,4 +7,14 @@ export declare function typeReferenceToString(x: spec.TypeReference): string;
|
|
|
7
7
|
* Return whether the given type references are equal
|
|
8
8
|
*/
|
|
9
9
|
export declare function typeReferenceEqual(a: spec.TypeReference, b: spec.TypeReference): boolean;
|
|
10
|
+
export type TypeResolver = (typeRef: string | spec.NamedTypeReference) => spec.Type | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a type resolver function for a given context (assembly + dependency closure).
|
|
13
|
+
*/
|
|
14
|
+
export declare function createTypeResolver(assembly: spec.Assembly, dependencyClosure: readonly spec.Assembly[]): TypeResolver;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a type from a name to the actual type.
|
|
17
|
+
* Uses a given assembly and dependency closure for lookup.
|
|
18
|
+
*/
|
|
19
|
+
export declare function resolveType(typeRef: string | spec.NamedTypeReference, assembly: spec.Assembly, dependencyClosure: readonly spec.Assembly[]): spec.Type | undefined;
|
|
10
20
|
//# sourceMappingURL=type-reference.d.ts.map
|
package/lib/type-reference.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.typeReferenceToString = typeReferenceToString;
|
|
4
4
|
exports.typeReferenceEqual = typeReferenceEqual;
|
|
5
|
+
exports.createTypeResolver = createTypeResolver;
|
|
6
|
+
exports.resolveType = resolveType;
|
|
5
7
|
const spec = require("@jsii/spec");
|
|
6
8
|
const type_visitor_1 = require("./type-visitor");
|
|
7
9
|
/**
|
|
@@ -49,4 +51,25 @@ function typeReferenceEqual(a, b) {
|
|
|
49
51
|
}
|
|
50
52
|
return false;
|
|
51
53
|
}
|
|
54
|
+
/**
|
|
55
|
+
* Creates a type resolver function for a given context (assembly + dependency closure).
|
|
56
|
+
*/
|
|
57
|
+
function createTypeResolver(assembly, dependencyClosure) {
|
|
58
|
+
return (typeRef) => resolveType(typeRef, assembly, dependencyClosure);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve a type from a name to the actual type.
|
|
62
|
+
* Uses a given assembly and dependency closure for lookup.
|
|
63
|
+
*/
|
|
64
|
+
function resolveType(typeRef, assembly, dependencyClosure) {
|
|
65
|
+
if (typeof typeRef !== 'string') {
|
|
66
|
+
typeRef = typeRef.fqn;
|
|
67
|
+
}
|
|
68
|
+
const [assm] = typeRef.split('.');
|
|
69
|
+
if (assembly.name === assm) {
|
|
70
|
+
return assembly.types?.[typeRef];
|
|
71
|
+
}
|
|
72
|
+
const foreignAssm = dependencyClosure.find((dep) => dep.name === assm);
|
|
73
|
+
return foreignAssm?.types?.[typeRef];
|
|
74
|
+
}
|
|
52
75
|
//# sourceMappingURL=type-reference.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-reference.js","sourceRoot":"","sources":["../src/type-reference.ts"],"names":[],"mappings":";;AAMA,sDAkBC;AAKD,gDAyBC;
|
|
1
|
+
{"version":3,"file":"type-reference.js","sourceRoot":"","sources":["../src/type-reference.ts"],"names":[],"mappings":"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","sourcesContent":["import * as spec from '@jsii/spec';\nimport { visitTypeReference } from './type-visitor';\n\n/**\n * Convert a type reference to a string\n */\nexport function typeReferenceToString(x: spec.TypeReference): string {\n return visitTypeReference<string>(x, {\n named: function (ref: spec.NamedTypeReference) {\n return ref.fqn;\n },\n primitive: function (ref: spec.PrimitiveTypeReference) {\n return ref.primitive;\n },\n collection: function (ref: spec.CollectionTypeReference) {\n return `${ref.collection.kind}<${typeReferenceToString(ref.collection.elementtype)}>`;\n },\n union: function (ref: spec.UnionTypeReference) {\n return ref.union.types.map(typeReferenceToString).join(' | ');\n },\n intersection: function (ref: spec.IntersectionTypeReference) {\n return ref.intersection.types.map(typeReferenceToString).join(' & ');\n },\n });\n}\n\n/**\n * Return whether the given type references are equal\n */\nexport function typeReferenceEqual(a: spec.TypeReference, b: spec.TypeReference): boolean {\n if (spec.isNamedTypeReference(a) && spec.isNamedTypeReference(b)) {\n return a.fqn === b.fqn;\n }\n if (spec.isPrimitiveTypeReference(a) && spec.isPrimitiveTypeReference(b)) {\n return a.primitive === b.primitive;\n }\n if (spec.isCollectionTypeReference(a) && spec.isCollectionTypeReference(b)) {\n return (\n a.collection.kind === b.collection.kind && typeReferenceEqual(a.collection.elementtype, b.collection.elementtype)\n );\n }\n if (spec.isUnionTypeReference(a) && spec.isUnionTypeReference(b)) {\n return (\n a.union.types.length === b.union.types.length &&\n a.union.types.every((aType, i) => typeReferenceEqual(aType, b.union.types[i]))\n );\n }\n if (spec.isIntersectionTypeReference(a) && spec.isIntersectionTypeReference(b)) {\n return (\n a.intersection.types.length === b.intersection.types.length &&\n a.intersection.types.every((aType, i) => typeReferenceEqual(aType, b.intersection.types[i]))\n );\n }\n return false;\n}\n\nexport type TypeResolver = (typeRef: string | spec.NamedTypeReference) => spec.Type | undefined;\n\n/**\n * Creates a type resolver function for a given context (assembly + dependency closure).\n */\nexport function createTypeResolver(assembly: spec.Assembly, dependencyClosure: readonly spec.Assembly[]): TypeResolver {\n return (typeRef) => resolveType(typeRef, assembly, dependencyClosure);\n}\n\n/**\n * Resolve a type from a name to the actual type.\n * Uses a given assembly and dependency closure for lookup.\n */\nexport function resolveType(\n typeRef: string | spec.NamedTypeReference,\n assembly: spec.Assembly,\n dependencyClosure: readonly spec.Assembly[],\n): spec.Type | undefined {\n if (typeof typeRef !== 'string') {\n typeRef = typeRef.fqn;\n }\n const [assm] = typeRef.split('.');\n if (assembly.name === assm) {\n return assembly.types?.[typeRef];\n }\n const foreignAssm = dependencyClosure.find((dep) => dep.name === assm);\n return foreignAssm?.types?.[typeRef];\n}\n"]}
|
package/lib/validator.d.ts
CHANGED
|
@@ -3,13 +3,17 @@ import * as ts from 'typescript';
|
|
|
3
3
|
import { Emitter } from './emitter';
|
|
4
4
|
import { JsiiDiagnostic } from './jsii-diagnostic';
|
|
5
5
|
import { ProjectInfo } from './project-info';
|
|
6
|
+
export interface ValidationResult extends ts.EmitResult {
|
|
7
|
+
readonly usedFeatures?: spec.JsiiFeature[];
|
|
8
|
+
}
|
|
6
9
|
export declare class Validator implements Emitter {
|
|
7
10
|
readonly projectInfo: ProjectInfo;
|
|
8
11
|
readonly assembly: spec.Assembly;
|
|
9
12
|
static VALIDATIONS: ValidationFunction[];
|
|
10
13
|
constructor(projectInfo: ProjectInfo, assembly: spec.Assembly);
|
|
11
|
-
emit():
|
|
14
|
+
emit(): ValidationResult;
|
|
12
15
|
}
|
|
13
16
|
export type DiagnosticEmitter = (diag: JsiiDiagnostic) => void;
|
|
14
|
-
export type
|
|
17
|
+
export type FeatureTracker = (feat: spec.JsiiFeature) => void;
|
|
18
|
+
export type ValidationFunction = (validator: Validator, assembly: spec.Assembly, diagnostic: DiagnosticEmitter, useFeatures: FeatureTracker) => void;
|
|
15
19
|
//# sourceMappingURL=validator.d.ts.map
|
package/lib/validator.js
CHANGED
|
@@ -9,6 +9,8 @@ const Case = require("./case");
|
|
|
9
9
|
const jsii_diagnostic_1 = require("./jsii-diagnostic");
|
|
10
10
|
const node_bindings_1 = require("./node-bindings");
|
|
11
11
|
const bindings = require("./node-bindings");
|
|
12
|
+
const type_analysis_1 = require("./type-analysis");
|
|
13
|
+
const type_reference_1 = require("./type-reference");
|
|
12
14
|
class Validator {
|
|
13
15
|
constructor(projectInfo, assembly) {
|
|
14
16
|
this.projectInfo = projectInfo;
|
|
@@ -16,12 +18,14 @@ class Validator {
|
|
|
16
18
|
}
|
|
17
19
|
emit() {
|
|
18
20
|
const diagnostics = new Array();
|
|
21
|
+
const usedFeatures = new Array();
|
|
19
22
|
for (const validation of Validator.VALIDATIONS) {
|
|
20
|
-
validation(this, this.assembly, diagnostics.push.bind(diagnostics));
|
|
23
|
+
validation(this, this.assembly, diagnostics.push.bind(diagnostics), usedFeatures.push.bind(usedFeatures));
|
|
21
24
|
}
|
|
22
25
|
return {
|
|
23
26
|
diagnostics: diagnostics,
|
|
24
27
|
emitSkipped: diagnostics.some((diag) => diag.category === ts.DiagnosticCategory.Error),
|
|
28
|
+
usedFeatures,
|
|
25
29
|
};
|
|
26
30
|
}
|
|
27
31
|
}
|
|
@@ -34,7 +38,7 @@ function _defaultValidations() {
|
|
|
34
38
|
_staticConstantNamesMustUseUpperSnakeCase,
|
|
35
39
|
_memberNamesMustNotLookLikeJavaGettersOrSetters,
|
|
36
40
|
_allTypeReferencesAreValid,
|
|
37
|
-
|
|
41
|
+
_inheritanceDoesNotChangeContracts,
|
|
38
42
|
_staticMembersAndNestedTypesMustNotSharePascalCaseName,
|
|
39
43
|
_abstractClassesMustImplementAllProperties,
|
|
40
44
|
];
|
|
@@ -107,7 +111,8 @@ function _defaultValidations() {
|
|
|
107
111
|
}
|
|
108
112
|
}
|
|
109
113
|
}
|
|
110
|
-
function
|
|
114
|
+
function _inheritanceDoesNotChangeContracts(validator, assembly, diagnostic, useFeature) {
|
|
115
|
+
const _dereference = (0, type_reference_1.createTypeResolver)(assembly, validator.projectInfo.dependencyClosure);
|
|
111
116
|
for (const type of _allTypes(assembly)) {
|
|
112
117
|
if (spec.isClassType(type)) {
|
|
113
118
|
for (const method of type.methods ?? []) {
|
|
@@ -147,7 +152,7 @@ function _defaultValidations() {
|
|
|
147
152
|
}
|
|
148
153
|
if (spec.isClassType(type) && type.base) {
|
|
149
154
|
// We have a parent class, collect their concrete members, too (recursively)...
|
|
150
|
-
const base = _dereference(type.base
|
|
155
|
+
const base = _dereference(type.base);
|
|
151
156
|
assert(base != null && spec.isClassType(base));
|
|
152
157
|
for (const member of _allImplementations(base, getter)) {
|
|
153
158
|
if (known.has(member.name)) {
|
|
@@ -175,7 +180,7 @@ function _defaultValidations() {
|
|
|
175
180
|
if (!type.base) {
|
|
176
181
|
return false;
|
|
177
182
|
}
|
|
178
|
-
const baseType = _dereference(type.base
|
|
183
|
+
const baseType = _dereference(type.base);
|
|
179
184
|
if (!baseType) {
|
|
180
185
|
return false;
|
|
181
186
|
}
|
|
@@ -183,7 +188,9 @@ function _defaultValidations() {
|
|
|
183
188
|
if (!overridden) {
|
|
184
189
|
return _validateMethodOverride(method, baseType);
|
|
185
190
|
}
|
|
186
|
-
_assertSignaturesMatch(overridden, method, `${type.fqn}#${method.name}`, `overriding ${baseType.fqn}
|
|
191
|
+
_assertSignaturesMatch(overridden, method, `${type.fqn}#${method.name}`, `overriding ${baseType.fqn}`, {
|
|
192
|
+
allowReturnTypeCovariance: true,
|
|
193
|
+
});
|
|
187
194
|
method.overrides = baseType.fqn;
|
|
188
195
|
return true;
|
|
189
196
|
}
|
|
@@ -191,7 +198,7 @@ function _defaultValidations() {
|
|
|
191
198
|
if (!type.base) {
|
|
192
199
|
return false;
|
|
193
200
|
}
|
|
194
|
-
const baseType = _dereference(type.base
|
|
201
|
+
const baseType = _dereference(type.base);
|
|
195
202
|
if (!baseType) {
|
|
196
203
|
return false;
|
|
197
204
|
}
|
|
@@ -199,7 +206,9 @@ function _defaultValidations() {
|
|
|
199
206
|
if (!overridden) {
|
|
200
207
|
return _validatePropertyOverride(property, baseType);
|
|
201
208
|
}
|
|
202
|
-
_assertPropertiesMatch(overridden, property, `${type.fqn}#${property.name}`, `overriding ${baseType.fqn}
|
|
209
|
+
_assertPropertiesMatch(overridden, property, `${type.fqn}#${property.name}`, `overriding ${baseType.fqn}`, {
|
|
210
|
+
allowCovariance: true,
|
|
211
|
+
});
|
|
203
212
|
property.overrides = baseType.fqn;
|
|
204
213
|
return true;
|
|
205
214
|
}
|
|
@@ -207,15 +216,17 @@ function _defaultValidations() {
|
|
|
207
216
|
if (!type.interfaces) {
|
|
208
217
|
// Abstract classes may not directly implement all members, need to check their supertypes...
|
|
209
218
|
if (spec.isClassType(type) && type.base && type.abstract) {
|
|
210
|
-
return _validateMethodImplementation(method, _dereference(type.base
|
|
219
|
+
return _validateMethodImplementation(method, _dereference(type.base));
|
|
211
220
|
}
|
|
212
221
|
return false;
|
|
213
222
|
}
|
|
214
223
|
for (const iface of type.interfaces) {
|
|
215
|
-
const ifaceType = _dereference(iface
|
|
224
|
+
const ifaceType = _dereference(iface);
|
|
216
225
|
const implemented = (ifaceType.methods ?? []).find((m) => m.name === method.name);
|
|
217
226
|
if (implemented) {
|
|
218
|
-
_assertSignaturesMatch(implemented, method, `${type.fqn}#${method.name}`, `implementing ${ifaceType.fqn}
|
|
227
|
+
_assertSignaturesMatch(implemented, method, `${type.fqn}#${method.name}`, `implementing ${ifaceType.fqn}`, {
|
|
228
|
+
allowReturnTypeCovariance: false,
|
|
229
|
+
});
|
|
219
230
|
// We won't replace a previous overrides declaration from a method override, as those have
|
|
220
231
|
// higher precedence than an initial implementation.
|
|
221
232
|
method.overrides = method.overrides ?? iface;
|
|
@@ -231,15 +242,15 @@ function _defaultValidations() {
|
|
|
231
242
|
if (!type.interfaces) {
|
|
232
243
|
// Abstract classes may not directly implement all members, need to check their supertypes...
|
|
233
244
|
if (spec.isClassType(type) && type.base && type.abstract) {
|
|
234
|
-
return _validatePropertyImplementation(property, _dereference(type.base
|
|
245
|
+
return _validatePropertyImplementation(property, _dereference(type.base));
|
|
235
246
|
}
|
|
236
247
|
return false;
|
|
237
248
|
}
|
|
238
249
|
for (const iface of type.interfaces) {
|
|
239
|
-
const ifaceType = _dereference(iface
|
|
250
|
+
const ifaceType = _dereference(iface);
|
|
240
251
|
const implemented = (ifaceType.properties ?? []).find((p) => p.name === property.name);
|
|
241
252
|
if (implemented) {
|
|
242
|
-
_assertPropertiesMatch(implemented, property, `${type.fqn}#${property.name}`, `implementing ${ifaceType.fqn}
|
|
253
|
+
_assertPropertiesMatch(implemented, property, `${type.fqn}#${property.name}`, `implementing ${ifaceType.fqn}`, { allowCovariance: false });
|
|
243
254
|
// We won't replace a previous overrides declaration from a property override, as those
|
|
244
255
|
// have higher precedence than an initial implementation.
|
|
245
256
|
property.overrides = property.overrides ?? ifaceType.fqn;
|
|
@@ -251,16 +262,30 @@ function _defaultValidations() {
|
|
|
251
262
|
}
|
|
252
263
|
return false;
|
|
253
264
|
}
|
|
254
|
-
function _assertSignaturesMatch(expected, actual, label, action) {
|
|
265
|
+
function _assertSignaturesMatch(expected, actual, label, action, opts) {
|
|
255
266
|
if (!!expected.protected !== !!actual.protected) {
|
|
256
267
|
const expVisibility = expected.protected ? 'protected' : 'public';
|
|
257
268
|
const actVisibility = actual.protected ? 'protected' : 'public';
|
|
258
269
|
diagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_5002_OVERRIDE_CHANGES_VISIBILITY.createDetached(label, action, actVisibility, expVisibility));
|
|
259
270
|
}
|
|
271
|
+
// Types must generally be the same, but can be covariant sometimes
|
|
260
272
|
if (!deepEqual(actual.returns, expected.returns)) {
|
|
261
|
-
const
|
|
262
|
-
const
|
|
263
|
-
|
|
273
|
+
const actualReturnType = actual.returns?.type;
|
|
274
|
+
const expectedReturnType = expected.returns?.type;
|
|
275
|
+
if (
|
|
276
|
+
// return type covariance is allowed
|
|
277
|
+
opts.allowReturnTypeCovariance &&
|
|
278
|
+
// static members can never change
|
|
279
|
+
!actual.static &&
|
|
280
|
+
// this is a valid covariant return type (actual is more specific than expected)
|
|
281
|
+
(0, type_analysis_1.isAllowedCovariantSubtype)(actualReturnType, expectedReturnType, _dereference)) {
|
|
282
|
+
useFeature('class-covariant-overrides');
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
const expType = spec.describeTypeReference(expectedReturnType);
|
|
286
|
+
const actType = spec.describeTypeReference(actualReturnType);
|
|
287
|
+
diagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_5003_OVERRIDE_CHANGES_RETURN_TYPE.createDetached(label, action, actType, expType));
|
|
288
|
+
}
|
|
264
289
|
}
|
|
265
290
|
const expectedParams = expected.parameters ?? [];
|
|
266
291
|
const actualParams = actual.parameters ?? [];
|
|
@@ -283,7 +308,7 @@ function _defaultValidations() {
|
|
|
283
308
|
}
|
|
284
309
|
}
|
|
285
310
|
}
|
|
286
|
-
function _assertPropertiesMatch(expected, actual, label, action) {
|
|
311
|
+
function _assertPropertiesMatch(expected, actual, label, action, opts) {
|
|
287
312
|
const actualNode = bindings.getPropertyRelatedNode(actual);
|
|
288
313
|
const expectedNode = bindings.getPropertyRelatedNode(expected);
|
|
289
314
|
if (!!expected.protected !== !!actual.protected) {
|
|
@@ -291,8 +316,21 @@ function _defaultValidations() {
|
|
|
291
316
|
const actVisibility = actual.protected ? 'protected' : 'public';
|
|
292
317
|
diagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_5002_OVERRIDE_CHANGES_VISIBILITY.create(actualNode?.modifiers?.find((mod) => mod.kind === ts.SyntaxKind.PublicKeyword || mod.kind === ts.SyntaxKind.ProtectedKeyword) ?? declarationName(actualNode), label, action, actVisibility, expVisibility).maybeAddRelatedInformation(expectedNode?.modifiers?.find((mod) => mod.kind === ts.SyntaxKind.PublicKeyword || mod.kind === ts.SyntaxKind.ProtectedKeyword) ?? declarationName(expectedNode), 'The implemented declaration is here.'));
|
|
293
318
|
}
|
|
294
|
-
|
|
295
|
-
|
|
319
|
+
// Types must generally be the same, but can be covariant sometimes
|
|
320
|
+
if (!deepEqual(actual.type, expected.type)) {
|
|
321
|
+
if (
|
|
322
|
+
// return type covariance is allowed
|
|
323
|
+
opts.allowCovariance &&
|
|
324
|
+
// static members can never change
|
|
325
|
+
!actual.static &&
|
|
326
|
+
// immutable properties may change in some case, as long as they are covariant
|
|
327
|
+
actual.immutable &&
|
|
328
|
+
(0, type_analysis_1.isAllowedCovariantSubtype)(actual.type, expected.type, _dereference)) {
|
|
329
|
+
useFeature('class-covariant-overrides');
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
diagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_5004_OVERRIDE_CHANGES_PROP_TYPE.create(actualNode?.type ?? declarationName(actualNode), label, action, actual.type, expected.type).maybeAddRelatedInformation(expectedNode?.type ?? declarationName(expectedNode), 'The implemented declaration is here.'));
|
|
333
|
+
}
|
|
296
334
|
}
|
|
297
335
|
if (expected.immutable !== actual.immutable) {
|
|
298
336
|
diagnostic(jsii_diagnostic_1.JsiiDiagnostic.JSII_5010_OVERRIDE_CHANGES_MUTABILITY.create(actualNode?.modifiers?.find((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword) ??
|
|
@@ -316,6 +354,7 @@ function _defaultValidations() {
|
|
|
316
354
|
* don't want to give an implementation yet.
|
|
317
355
|
*/
|
|
318
356
|
function _abstractClassesMustImplementAllProperties(validator, assembly, diagnostic) {
|
|
357
|
+
const _dereference = (0, type_reference_1.createTypeResolver)(assembly, validator.projectInfo.dependencyClosure);
|
|
319
358
|
for (const type of _allTypes(assembly)) {
|
|
320
359
|
if (!spec.isClassType(type) || !type.abstract) {
|
|
321
360
|
continue;
|
|
@@ -333,7 +372,7 @@ function _defaultValidations() {
|
|
|
333
372
|
into.add(prop.name);
|
|
334
373
|
}
|
|
335
374
|
if (type.base) {
|
|
336
|
-
const base = _dereference(type.base
|
|
375
|
+
const base = _dereference(type.base);
|
|
337
376
|
if (spec.isClassType(base)) {
|
|
338
377
|
collectClassProps(base, into);
|
|
339
378
|
}
|
|
@@ -341,7 +380,7 @@ function _defaultValidations() {
|
|
|
341
380
|
return into;
|
|
342
381
|
}
|
|
343
382
|
function checkInterfacePropsImplemented(interfaceFqn, cls, propNames) {
|
|
344
|
-
const intf = _dereference(interfaceFqn
|
|
383
|
+
const intf = _dereference(interfaceFqn);
|
|
345
384
|
if (!spec.isInterfaceType(intf)) {
|
|
346
385
|
return;
|
|
347
386
|
}
|
|
@@ -482,17 +521,6 @@ function _allTypeReferences(assm) {
|
|
|
482
521
|
}
|
|
483
522
|
}
|
|
484
523
|
}
|
|
485
|
-
function _dereference(typeRef, assembly, validator) {
|
|
486
|
-
if (typeof typeRef !== 'string') {
|
|
487
|
-
typeRef = typeRef.fqn;
|
|
488
|
-
}
|
|
489
|
-
const [assm] = typeRef.split('.');
|
|
490
|
-
if (assembly.name === assm) {
|
|
491
|
-
return assembly.types?.[typeRef];
|
|
492
|
-
}
|
|
493
|
-
const foreignAssm = validator.projectInfo.dependencyClosure.find((dep) => dep.name === assm);
|
|
494
|
-
return foreignAssm?.types?.[typeRef];
|
|
495
|
-
}
|
|
496
524
|
function _isEmpty(array) {
|
|
497
525
|
return array == null || array.length === 0;
|
|
498
526
|
}
|