@@ -18,6 +18,11 @@ import {
1818} from '../utils/plugin-utils' ;
1919import { AbstractFileVisitor } from './abstract.visitor' ;
2020
21+ const [ tsVersionMajor , tsVersionMinor ] = ts . versionMajorMinor
22+ ?. split ( '.' )
23+ . map ( ( x ) => + x ) ;
24+ const isInUpdatedAstContext = tsVersionMinor >= 8 || tsVersionMajor > 4 ;
25+
2126export class ControllerClassVisitor extends AbstractFileVisitor {
2227 visit (
2328 sourceFile : ts . SourceFile ,
@@ -26,7 +31,7 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
2631 options : PluginOptions
2732 ) {
2833 const typeChecker = program . getTypeChecker ( ) ;
29- sourceFile = this . updateImports ( sourceFile , ctx . factory ) ;
34+ sourceFile = this . updateImports ( sourceFile , ctx . factory , program ) ;
3035
3136 const visitNode = ( node : ts . Node ) : ts . Node => {
3237 if ( ts . isMethodDeclaration ( node ) ) {
@@ -56,14 +61,18 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
5661 hostFilename : string ,
5762 sourceFile : ts . SourceFile
5863 ) : ts . MethodDeclaration {
59- if ( ! compilerNode . decorators ) {
64+ // Support both >= v4.8 and v4.7 and lower
65+ const decorators = ( ts as any ) . canHaveDecorators
66+ ? ( ts as any ) . getDecorators ( compilerNode )
67+ : compilerNode . decorators ;
68+ if ( ! decorators ) {
6069 return compilerNode ;
6170 }
6271
6372 const apiOperationDecoratorsArray = this . createApiOperationDecorator (
6473 factory ,
6574 compilerNode ,
66- compilerNode . decorators ,
75+ decorators ,
6776 options ,
6877 sourceFile ,
6978 typeChecker
@@ -72,43 +81,60 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
7281 apiOperationDecoratorsArray . length > 0 ;
7382
7483 const existingDecorators = removeExistingApiOperationDecorator
75- ? compilerNode . decorators . filter (
84+ ? decorators . filter (
7685 ( item ) => getDecoratorName ( item ) !== ApiOperation . name
7786 )
78- : compilerNode . decorators ;
87+ : decorators ;
7988
80- return factory . updateMethodDeclaration (
81- compilerNode ,
82- [
83- ... apiOperationDecoratorsArray ,
84- ... existingDecorators ,
85- factory . createDecorator (
86- factory . createCallExpression (
87- factory . createIdentifier (
88- ` ${ OPENAPI_NAMESPACE } . ${ ApiResponse . name } `
89- ) ,
90- undefined ,
91- [
92- this . createDecoratorObjectLiteralExpr (
93- factory ,
94- compilerNode ,
95- typeChecker ,
96- factory . createNodeArray ( ) ,
97- hostFilename
98- )
99- ]
100- )
89+ // Support both >= v4.8 and v4.7 and lower
90+ const modifiers = isInUpdatedAstContext
91+ ? ( ts as any ) . getModifiers ( compilerNode )
92+ : compilerNode . modifiers ;
93+
94+ const updatedDecorators = [
95+ ... apiOperationDecoratorsArray ,
96+ ... existingDecorators ,
97+ factory . createDecorator (
98+ factory . createCallExpression (
99+ factory . createIdentifier ( ` ${ OPENAPI_NAMESPACE } . ${ ApiResponse . name } ` ) ,
100+ undefined ,
101+ [
102+ this . createDecoratorObjectLiteralExpr (
103+ factory ,
104+ compilerNode ,
105+ typeChecker ,
106+ factory . createNodeArray ( ) ,
107+ hostFilename
108+ )
109+ ]
101110 )
102- ] ,
103- compilerNode . modifiers ,
104- compilerNode . asteriskToken ,
105- compilerNode . name ,
106- compilerNode . questionToken ,
107- compilerNode . typeParameters ,
108- compilerNode . parameters ,
109- compilerNode . type ,
110- compilerNode . body
111- ) ;
111+ )
112+ ] ;
113+
114+ return isInUpdatedAstContext
115+ ? ( factory as any ) . updateMethodDeclaration (
116+ compilerNode ,
117+ [ ...updatedDecorators , ...modifiers ] ,
118+ compilerNode . asteriskToken ,
119+ compilerNode . name ,
120+ compilerNode . questionToken ,
121+ compilerNode . typeParameters ,
122+ compilerNode . parameters ,
123+ compilerNode . type ,
124+ compilerNode . body
125+ )
126+ : factory . updateMethodDeclaration (
127+ compilerNode ,
128+ updatedDecorators ,
129+ modifiers ,
130+ compilerNode . asteriskToken ,
131+ compilerNode . name ,
132+ compilerNode . questionToken ,
133+ compilerNode . typeParameters ,
134+ compilerNode . parameters ,
135+ compilerNode . type ,
136+ compilerNode . body
137+ ) ;
112138 }
113139
114140 createApiOperationDecorator (
@@ -125,7 +151,8 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
125151 const keyToGenerate = options . controllerKeyOfComment ;
126152 const apiOperationDecorator = getDecoratorOrUndefinedByNames (
127153 [ ApiOperation . name ] ,
128- nodeArray
154+ nodeArray ,
155+ factory
129156 ) ;
130157 const apiOperationExpr : ts . ObjectLiteralExpression | undefined =
131158 apiOperationDecorator &&
@@ -248,18 +275,26 @@ export class ControllerClassVisitor extends AbstractFileVisitor {
248275 }
249276
250277 getStatusCodeIdentifier ( factory : ts . NodeFactory , node : ts . MethodDeclaration ) {
251- const decorators = node . decorators ;
278+ // Support both >= v4.8 and v4.7 and lower
279+ const decorators = ( ts as any ) . canHaveDecorators
280+ ? ( ts as any ) . getDecorators ( node )
281+ : node . decorators ;
252282 const httpCodeDecorator = getDecoratorOrUndefinedByNames (
253283 [ 'HttpCode' ] ,
254- decorators
284+ decorators ,
285+ factory
255286 ) ;
256287 if ( httpCodeDecorator ) {
257288 const argument = head ( getDecoratorArguments ( httpCodeDecorator ) ) ;
258289 if ( argument ) {
259290 return argument ;
260291 }
261292 }
262- const postDecorator = getDecoratorOrUndefinedByNames ( [ 'Post' ] , decorators ) ;
293+ const postDecorator = getDecoratorOrUndefinedByNames (
294+ [ 'Post' ] ,
295+ decorators ,
296+ factory
297+ ) ;
263298 if ( postDecorator ) {
264299 return factory . createIdentifier ( '201' ) ;
265300 }
0 commit comments