@@ -3,7 +3,7 @@ import * as Path from "path";
33import ts from "typescript" ;
44
55import * as TypeScriptCodeGenerator from "../../CodeGenerator" ;
6- import { DevelopmentError , NotFoundReference } from "../../Exception" ;
6+ import { DevelopmentError } from "../../Exception" ;
77import { Store } from "./store" ;
88import * as ToTypeNode from "./toTypeNode" ;
99
@@ -24,54 +24,67 @@ const generatePath = (entryPoint: string, currentPoint: string, referencePath: s
2424 } ;
2525} ;
2626
27- const generateName = ( store : Store . Type , base : string , pathArray : string [ ] ) : string => {
27+ const calculateReferencePath = ( store : Store . Type , base : string , pathArray : string [ ] ) : ToTypeNode . ResolveReferencePath => {
2828 let names : string [ ] = [ ] ;
29+ let unresolvedPaths : string [ ] = [ ] ;
2930 pathArray . reduce ( ( previous , lastPath , index ) => {
3031 const current = Path . join ( previous , lastPath ) ;
3132 // ディレクトリが深い場合は相対パスが`..`を繰り返す可能性があり、
3233 // その場合はすでに登録されたnamesを削除する
3334 if ( lastPath === ".." && names . length > 0 ) {
3435 names = names . slice ( 0 , names . length - 1 ) ;
3536 }
36- const isLast = index === pathArray . length - 1 ;
37- if ( isLast ) {
37+ const isFinalPath = index === pathArray . length - 1 ;
38+ if ( isFinalPath ) {
3839 const statement = store . getStatement ( current , "interface" ) ;
3940 const statement2 = store . getStatement ( current , "typeAlias" ) ;
4041 const statement3 = store . getStatement ( current , "namespace" ) ;
4142 if ( statement ) {
4243 names . push ( statement . name ) ;
44+ return current ;
4345 } else if ( statement2 ) {
4446 names . push ( statement2 . name ) ;
47+ return current ;
4548 } else if ( statement3 ) {
4649 names . push ( statement3 . name ) ;
50+ return current ;
51+ } else {
52+ unresolvedPaths . push ( lastPath ) ;
4753 }
4854 } else {
4955 const statement = store . getStatement ( current , "namespace" ) ;
5056 if ( statement ) {
51- names . push ( statement . value . name . text ) ;
57+ unresolvedPaths = unresolvedPaths . slice ( 0 , unresolvedPaths . length - 1 ) ;
58+ names . push ( statement . name ) ;
59+ } else {
60+ unresolvedPaths . push ( lastPath ) ;
5261 }
5362 }
5463 return current ;
5564 } , base ) ;
5665 if ( names . length === 0 ) {
5766 throw new DevelopmentError ( "Local Reference Error \n" + JSON . stringify ( { pathArray, names, base } , null , 2 ) ) ;
5867 }
59- return names . join ( "." ) ;
68+ return {
69+ name : names . join ( "." ) ,
70+ maybeResolvedName : names . concat ( unresolvedPaths ) . join ( "." ) ,
71+ unresolvedPaths,
72+ } ;
6073} ;
6174
6275export const create = ( entryPoint : string , store : Store . Type , factory : TypeScriptCodeGenerator . Factory . Type ) : ToTypeNode . Context => {
63- const getReferenceName : ToTypeNode . Context [ "getReferenceName " ] = ( currentPoint , referencePath ) : string => {
76+ const resolveReferencePath : ToTypeNode . Context [ "resolveReferencePath " ] = ( currentPoint , referencePath ) => {
6477 const { pathArray, base } = generatePath ( entryPoint , currentPoint , referencePath ) ;
65- return generateName ( store , base , pathArray ) ;
78+ return calculateReferencePath ( store , base , pathArray ) ;
6679 } ;
67- const setReferenceHandler : ToTypeNode . Context [ "setReferenceHandler" ] = reference => {
80+ const setReferenceHandler : ToTypeNode . Context [ "setReferenceHandler" ] = ( currentPoint , reference ) => {
6881 if ( store . hasStatement ( reference . path , [ "interface" , "typeAlias" ] ) ) {
6982 return ;
7083 }
7184 if ( reference . type === "remote" ) {
7285 const typeNode = ToTypeNode . convert ( entryPoint , reference . referencePoint , factory , reference . data , {
7386 setReferenceHandler,
74- getReferenceName ,
87+ resolveReferencePath ,
7588 } ) ;
7689 if ( ts . isTypeLiteralNode ( typeNode ) ) {
7790 store . addStatement ( reference . path , {
@@ -89,7 +102,7 @@ export const create = (entryPoint: string, store: Store.Type, factory: TypeScrip
89102 name : reference . name ,
90103 type : ToTypeNode . convert ( entryPoint , reference . referencePoint , factory , reference . data , {
91104 setReferenceHandler,
92- getReferenceName ,
105+ resolveReferencePath ,
93106 } ) ,
94107 } ) ;
95108 store . addStatement ( reference . path , {
@@ -99,10 +112,22 @@ export const create = (entryPoint: string, store: Store.Type, factory: TypeScrip
99112 } ) ;
100113 }
101114 } else if ( reference . type === "local" ) {
102- if ( ! store . hasStatement ( reference . path , [ "namespace" , "interface" , "typeAlias" ] ) ) {
103- throw new NotFoundReference ( `The schema ${ reference . name } is undefined in "${ reference . path } ".` ) ;
115+ if ( ! store . isAfterDefined ( reference . path ) ) {
116+ const { maybeResolvedName } = resolveReferencePath ( currentPoint , reference . path ) ;
117+ const value = factory . TypeAliasDeclaration . create ( {
118+ export : true ,
119+ name : reference . name ,
120+ type : factory . TypeReferenceNode . create ( {
121+ name : maybeResolvedName ,
122+ } ) ,
123+ } ) ;
124+ store . addStatement ( reference . path , {
125+ name : reference . name ,
126+ type : "typeAlias" ,
127+ value,
128+ } ) ;
104129 }
105130 }
106131 } ;
107- return { setReferenceHandler : setReferenceHandler , getReferenceName } ;
132+ return { setReferenceHandler : setReferenceHandler , resolveReferencePath : resolveReferencePath } ;
108133} ;
0 commit comments