1
1
import * as glob from "glob" ;
2
2
import * as stringify from "json-stable-stringify" ;
3
3
import * as path from "path" ;
4
+ import { createHash } from "crypto" ;
4
5
import * as ts from "typescript" ;
5
6
export { Program , CompilerOptions , Symbol } from "typescript" ;
6
7
7
8
8
9
const vm = require ( "vm" ) ;
9
10
10
- const REGEX_FILE_NAME = / " .* " \. / ;
11
+ const REGEX_FILE_NAME_OR_SPACE = / ( \b i m p o r t \( " .* ? " \) | " . * ? " ) \. | / g ;
11
12
const REGEX_TSCONFIG_NAME = / ^ .* \. j s o n $ / ;
12
13
const REGEX_TJS_JSDOC = / ^ - ( [ \w ] + ) \s + ( \S | \S [ \s \S ] * \S ) \s * $ / g;
13
14
@@ -801,7 +802,7 @@ export class JsonSchemaGenerator {
801
802
return this . typeNamesById [ id ] ;
802
803
}
803
804
804
- const baseName = this . tc . typeToString ( typ , undefined , ts . TypeFormatFlags . UseFullyQualifiedType ) ;
805
+ const baseName = this . tc . typeToString ( typ , undefined , ts . TypeFormatFlags . NoTruncation | ts . TypeFormatFlags . UseFullyQualifiedType ) . replace ( REGEX_FILE_NAME_OR_SPACE , "" ) ;
805
806
let name = baseName ;
806
807
if ( this . typeNamesUsed [ name ] ) { // If a type with same name exists
807
808
for ( let i = 1 ; true ; ++ i ) { // Try appending "_1", "_2", etc.
@@ -855,13 +856,11 @@ export class JsonSchemaGenerator {
855
856
reffedType ! . getFlags ( ) & ts . SymbolFlags . Alias ?
856
857
this . tc . getAliasedSymbol ( reffedType ! ) :
857
858
reffedType !
858
- ) . replace ( REGEX_FILE_NAME , "" ) ;
859
+ ) . replace ( REGEX_FILE_NAME_OR_SPACE , "" ) ;
859
860
} else if ( asRef ) {
860
861
fullTypeName = this . getTypeName ( typ ) ;
861
862
}
862
863
863
- fullTypeName = fullTypeName . replace ( " " , "" ) ;
864
-
865
864
if ( asRef ) {
866
865
// We don't return the full definition, but we put it into
867
866
// reffedDefinitions below.
@@ -1036,6 +1035,10 @@ export function getProgramFromFiles(files: string[], jsonCompilerOptions: any =
1036
1035
return ts . createProgram ( files , options ) ;
1037
1036
}
1038
1037
1038
+ function generateHashOfNode ( node : ts . Node , relativePath : string ) {
1039
+ return createHash ( "md5" ) . update ( relativePath ) . update ( node . pos . toString ( ) ) . digest ( "hex" ) . substring ( 0 , 8 ) ;
1040
+ }
1041
+
1039
1042
export function buildGenerator ( program : ts . Program , args : PartialArgs = { } , onlyIncludeFiles ?: string [ ] ) : JsonSchemaGenerator | null {
1040
1043
function isUserFile ( file : ts . SourceFile ) : boolean {
1041
1044
if ( onlyIncludeFiles === undefined ) {
@@ -1065,8 +1068,11 @@ export function buildGenerator(program: ts.Program, args: PartialArgs = {}, only
1065
1068
const allSymbols : { [ name : string ] : ts . Type } = { } ;
1066
1069
const userSymbols : { [ name : string ] : ts . Symbol } = { } ;
1067
1070
const inheritingTypes : { [ baseName : string ] : string [ ] } = { } ;
1071
+ const workingDir = program . getCurrentDirectory ( ) ;
1068
1072
1069
1073
program . getSourceFiles ( ) . forEach ( ( sourceFile , _sourceFileIdx ) => {
1074
+ const relativePath = path . relative ( workingDir , sourceFile . fileName ) ;
1075
+
1070
1076
function inspect ( node : ts . Node , tc : ts . TypeChecker ) {
1071
1077
1072
1078
if ( node . kind === ts . SyntaxKind . ClassDeclaration
@@ -1078,7 +1084,7 @@ export function buildGenerator(program: ts.Program, args: PartialArgs = {}, only
1078
1084
const nodeType = tc . getTypeAtLocation ( node ) ;
1079
1085
const fullyQualifiedName = tc . getFullyQualifiedName ( symbol ) ;
1080
1086
const typeName = fullyQualifiedName . replace ( / " .* " \. / , "" ) ;
1081
- const name = ! args . uniqueNames ? typeName : `${ typeName } .${ ( < any > symbol ) . id } ` ;
1087
+ const name = ! args . uniqueNames ? typeName : `${ typeName } .${ generateHashOfNode ( node , relativePath ) } ` ;
1082
1088
1083
1089
symbols . push ( { name, typeName, fullyQualifiedName, symbol } ) ;
1084
1090
if ( ! userSymbols [ name ] ) {
0 commit comments