intergen: Do not add I-prefix to interfaces
Renaming of existing types turned out to be too complicated because the code depends on checker.typeToString, and there is no way that I know of that would allow renaming of an existing type.
This commit is contained in:
parent
25593dd994
commit
b122ff093a
@ -1,4 +1,3 @@
|
||||
export * from './build'
|
||||
export * from './newlib'
|
||||
export * from './intergen'
|
||||
export * from './typecheck'
|
||||
|
||||
160
packages/scripts/src/commands/intergen.test.ts
Normal file
160
packages/scripts/src/commands/intergen.test.ts
Normal file
@ -0,0 +1,160 @@
|
||||
jest.mock('../log')
|
||||
|
||||
import {intergen} from './intergen'
|
||||
import * as fs from 'fs'
|
||||
import * as path from 'path'
|
||||
import * as os from 'os'
|
||||
|
||||
describe('intergen', () => {
|
||||
|
||||
const tmpdir = os.tmpdir()
|
||||
const templateName = 'intergen.tmp'
|
||||
|
||||
let sourceFiles: string[] = []
|
||||
let i = 0
|
||||
function createSourceFile(contents: string) {
|
||||
i++
|
||||
const sourceFile = path.join(tmpdir, templateName + i + '.ts')
|
||||
fs.writeFileSync(sourceFile, contents)
|
||||
sourceFiles.push(sourceFile)
|
||||
return sourceFile
|
||||
}
|
||||
|
||||
function execute(source: string): string {
|
||||
const file = createSourceFile(source)
|
||||
return intergen('intergen', '-i', file)
|
||||
}
|
||||
|
||||
afterEach(() => {
|
||||
sourceFiles.forEach(f => fs.unlinkSync(f))
|
||||
sourceFiles = []
|
||||
})
|
||||
|
||||
it('converts exported class into interface', () => {
|
||||
const result = execute(`export class Value {
|
||||
amount: number
|
||||
}`)
|
||||
expect(result).toEqual(`export interface Value {
|
||||
amount: number
|
||||
}`)
|
||||
})
|
||||
|
||||
it('does nothing when class is not exported', () => {
|
||||
const result = execute(`class Value {
|
||||
amount: number
|
||||
}`)
|
||||
expect(result).toEqual(``)
|
||||
})
|
||||
|
||||
it('converts inherited classes into interfaces', () => {
|
||||
const result = execute(`class A {
|
||||
a: number
|
||||
}
|
||||
export class B extends A {
|
||||
b: string
|
||||
}`)
|
||||
expect(result).toEqual(`export interface B {
|
||||
b: string
|
||||
a: number
|
||||
}`)
|
||||
})
|
||||
|
||||
it('converts referenced classes into interfaces', () => {
|
||||
const result = execute(`class A {
|
||||
a: number
|
||||
}
|
||||
export class B {
|
||||
a: A
|
||||
}`)
|
||||
expect(result).toEqual(`export interface B {
|
||||
a: A
|
||||
}
|
||||
|
||||
export interface A {
|
||||
a: number
|
||||
}`)
|
||||
})
|
||||
|
||||
it('correctly converts union properties', () => {
|
||||
const result = execute(`export class A {
|
||||
a: 'b' | 'c'
|
||||
}`)
|
||||
expect(result).toEqual(`export interface A {
|
||||
a: "b" | "c"
|
||||
}`)
|
||||
})
|
||||
|
||||
it('correctly converts array properties', () => {
|
||||
const result = execute(`class Name {
|
||||
firstName: string
|
||||
}
|
||||
|
||||
export class Names {
|
||||
names1: Name[]
|
||||
names2: Array<Name>
|
||||
names3: Name[][]
|
||||
names4: Array<Array<Name>>
|
||||
`)
|
||||
expect(result).toEqual(`export interface Names {
|
||||
names1: Name[]
|
||||
names2: Name[]
|
||||
names3: Name[][]
|
||||
names4: Name[][]
|
||||
}
|
||||
|
||||
export interface Name {
|
||||
firstName: string
|
||||
}`)
|
||||
})
|
||||
|
||||
it('correctly converts intersections', () => {
|
||||
const result = execute(`export class C {
|
||||
c: A & B
|
||||
}
|
||||
|
||||
class A {
|
||||
a: string
|
||||
}
|
||||
|
||||
class B {
|
||||
b: number
|
||||
}`)
|
||||
expect(result).toEqual(`export interface C {
|
||||
c: A & B
|
||||
}
|
||||
|
||||
export interface A {
|
||||
a: string
|
||||
}
|
||||
|
||||
export interface B {
|
||||
b: number
|
||||
}`)
|
||||
})
|
||||
|
||||
it('correctly converts inline property definitions', () => {
|
||||
const result = execute(`export class A {
|
||||
b: {a: string, c: number}
|
||||
}`)
|
||||
expect(result).toEqual(`export interface A {
|
||||
b: { a: string; c: number; }
|
||||
}`)
|
||||
})
|
||||
|
||||
it('correctly converts inline defs w/ references', () => {
|
||||
const result = execute(`class A {
|
||||
a: number
|
||||
}
|
||||
export class B {
|
||||
b: { a: A; c: number; }
|
||||
}`)
|
||||
expect(result).toEqual(`export interface B {
|
||||
b: { a: A; c: number; }
|
||||
}
|
||||
|
||||
export interface A {
|
||||
a: number
|
||||
}`)
|
||||
})
|
||||
|
||||
})
|
||||
@ -11,6 +11,11 @@ function isTypeReference(type: ts.ObjectType): type is ts.TypeReference {
|
||||
return !!(type.objectFlags & ts.ObjectFlags.Reference)
|
||||
}
|
||||
|
||||
function isAnonymous(type: ts.Type): boolean {
|
||||
return isObjectType(type) && !!(
|
||||
type.objectFlags & ts.ObjectFlags.Anonymous)
|
||||
}
|
||||
|
||||
function filterInvisibleProperties(type: ts.Symbol): boolean {
|
||||
const flags = ts.getCombinedModifierFlags(type.valueDeclaration)
|
||||
return !(flags & ts.ModifierFlags.NonPublicAccessibilityModifier)
|
||||
@ -51,7 +56,7 @@ interface IClassDefinition {
|
||||
*
|
||||
*/
|
||||
|
||||
export function typecheck(...argv: string[]) {
|
||||
export function intergen(...argv: string[]): string {
|
||||
const args = argparse({
|
||||
input: arg('string', {alias: 'i', required: true}),
|
||||
debug: arg('boolean'),
|
||||
@ -191,8 +196,8 @@ export function typecheck(...argv: string[]) {
|
||||
function isNodeExported(node: ts.Node): boolean {
|
||||
return (
|
||||
(ts.getCombinedModifierFlags(node as any) &
|
||||
ts.ModifierFlags.Export) !== 0 ||
|
||||
(!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
|
||||
ts.ModifierFlags.Export) !== 0
|
||||
// (!!node.parent && node.parent.kind === ts.SyntaxKind.SourceFile)
|
||||
)
|
||||
}
|
||||
|
||||
@ -296,7 +301,10 @@ export function typecheck(...argv: string[]) {
|
||||
properties: classProperties,
|
||||
}
|
||||
|
||||
classDefs.push(classDef)
|
||||
if (!isAnonymous(type)) {
|
||||
// Prevent defining anonymous declarations as interfaces
|
||||
classDefs.push(classDef)
|
||||
}
|
||||
typeDefinitions.set(type, classDef)
|
||||
|
||||
classDef.allRelevantTypes.forEach(handleType)
|
||||
@ -306,6 +314,11 @@ export function typecheck(...argv: string[]) {
|
||||
* Visit nodes finding exported classes
|
||||
*/
|
||||
function visit(node: ts.Node) {
|
||||
console.log(node.getText(),
|
||||
isNodeExported(node),
|
||||
ts.getCombinedModifierFlags(node as any),
|
||||
!!node.parent,
|
||||
node.parent.kind === ts.SyntaxKind.SourceFile)
|
||||
// Only consider exported nodes
|
||||
if (!isNodeExported(node)) {
|
||||
return
|
||||
@ -325,8 +338,12 @@ export function typecheck(...argv: string[]) {
|
||||
}
|
||||
|
||||
function setTypeName(type: ts.Type, mappings: Map<ts.Type, string>) {
|
||||
if (isAnonymous(type)) {
|
||||
return
|
||||
}
|
||||
const name = typeToString(type)
|
||||
mappings.set(type, `I${name}`)
|
||||
// (type as any).symbol.name = 'I' + type.symbol.name
|
||||
mappings.set(type, `${name}`)
|
||||
}
|
||||
|
||||
const nameMappings = new Map<ts.Type, string>()
|
||||
@ -339,7 +356,7 @@ export function typecheck(...argv: string[]) {
|
||||
|
||||
function createInterface(classDef: IClassDefinition): string {
|
||||
const name = nameMappings.get(classDef.type)!
|
||||
const start = `interface ${name} {`
|
||||
const start = `export interface ${name} {`
|
||||
const properties = classDef.properties.map(p => {
|
||||
return ` ${p.name}: ${nameMappings.get(p.type) || p.typeString}`
|
||||
})
|
||||
@ -362,4 +379,5 @@ export function typecheck(...argv: string[]) {
|
||||
} else {
|
||||
fs.writeFileSync(args.output, value)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
@ -1,12 +1,9 @@
|
||||
import {format} from 'util'
|
||||
|
||||
const stdout: NodeJS.WriteStream = process.stdout
|
||||
const stderr: NodeJS.WriteStream = process.stderr
|
||||
|
||||
export function error(message: string, ...values: any[]) {
|
||||
stderr.write(format(message + '\n', ...values))
|
||||
process.stderr.write(format(message + '\n', ...values))
|
||||
}
|
||||
|
||||
export function info(message: string, ...values: any[]) {
|
||||
stdout.write(format(message + '\n', ...values))
|
||||
process.stdout.write(format(message + '\n', ...values))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user