From 030493e6b3ece998ec05a2ab5e81cec6932e7098 Mon Sep 17 00:00:00 2001 From: Marcelo Shima Date: Thu, 2 May 2024 23:25:41 -0300 Subject: [PATCH] add parameters support to addJavaAnnotation --- .../java/support/add-java-annotation.spec.ts | 107 ++++++++++++++++++ .../java/support/add-java-annotation.ts | 53 +++++++-- .../generated-annotation-transform.spec.ts | 4 +- .../support/generated-annotation-transform.ts | 2 +- generators/java/support/index.ts | 2 +- 5 files changed, 157 insertions(+), 11 deletions(-) create mode 100644 generators/java/support/add-java-annotation.spec.ts diff --git a/generators/java/support/add-java-annotation.spec.ts b/generators/java/support/add-java-annotation.spec.ts new file mode 100644 index 000000000000..585c63e80eea --- /dev/null +++ b/generators/java/support/add-java-annotation.spec.ts @@ -0,0 +1,107 @@ +import { it, describe, expect } from 'esmocha'; +import { addJavaAnnotation, addJavaImport } from './add-java-annotation.js'; + +describe('generator > java', () => { + describe('addJavaImport', () => { + describe('not passing content', () => { + it('should return a function', () => { + expect(typeof addJavaImport('foo') === 'function').toBe(true); + }); + }); + + describe('passing content', () => { + it('should add the import', () => { + expect( + addJavaImport( + `package com.mycompany.myapp; +`, + 'com.mycompany.myapp.Foo', + ), + ).toBe(`package com.mycompany.myapp; +import com.mycompany.myapp.Foo; +`); + }); + + it('should add the import after a blank line', () => { + expect( + addJavaImport( + `package com.mycompany.myapp; + +`, + 'com.mycompany.myapp.Foo', + ), + ).toBe(`package com.mycompany.myapp; + +import com.mycompany.myapp.Foo; +`); + }); + + it('should add the static import', () => { + expect( + addJavaImport( + `package com.mycompany.myapp; +`, + 'com.mycompany.myapp.Foo', + { staticImport: true }, + ), + ).toBe(`package com.mycompany.myapp; +import static com.mycompany.myapp.Foo; +`); + }); + }); + }); + + describe('addJavaAnnotation', () => { + describe('not passing content', () => { + it('should return a function', () => { + expect(typeof addJavaAnnotation({ annotation: 'Foo' }) === 'function').toBe(true); + }); + }); + + describe('passing content', () => { + it('should add the annotation', () => { + expect( + addJavaAnnotation( + `package com.mycompany.myapp; + +public class MyTest {}`, + { annotation: 'Foo' }, + ), + ).toBe(`package com.mycompany.myapp; + +@Foo +public class MyTest {}`); + }); + + it('should add the annotation and import', () => { + expect( + addJavaAnnotation( + `package com.mycompany.myapp; + +public class MyTest {}`, + { annotation: 'Foo', package: 'com.mycompany.myapp' }, + ), + ).toBe(`package com.mycompany.myapp; + +import com.mycompany.myapp.Foo; +@Foo +public class MyTest {}`); + }); + + it('should add the annotation and import', () => { + expect( + addJavaAnnotation( + `package com.mycompany.myapp; + +public class MyTest {}`, + { annotation: 'Foo', package: 'com.mycompany.myapp', parameters: () => 'bar="baz"' }, + ), + ).toBe(`package com.mycompany.myapp; + +import com.mycompany.myapp.Foo; +@Foo(bar="baz") +public class MyTest {}`); + }); + }); + }); +}); diff --git a/generators/java/support/add-java-annotation.ts b/generators/java/support/add-java-annotation.ts index ec26a716411c..6bf2caec5051 100644 --- a/generators/java/support/add-java-annotation.ts +++ b/generators/java/support/add-java-annotation.ts @@ -16,17 +16,56 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +import { escapeRegExp } from 'lodash-es'; -export default function addJavaAnnotation(content: string, { package: packageName, annotation }: { package?: string; annotation: string }) { +export type JavaImportType = { staticImport?: boolean }; + +const addJavaImportToContent = (content: string, identifier: string, { staticImport }: JavaImportType = {}) => { + const importStatement = `import ${staticImport ? 'static ' : ''}${identifier};`; + return new RegExp(escapeRegExp(importStatement)).test(content) + ? content + : content.replace(/(package [\w.]+;\n\n?)/, `$1${importStatement}\n`); +}; + +export function addJavaImport(indentifier: string, type?: JavaImportType): (content: string) => string; +export function addJavaImport(content: string, identifierOrType: string, type?: JavaImportType): string; +export function addJavaImport( + contentOrIdentifier: string, + identifierOrType?: string | JavaImportType, + type?: JavaImportType, +): string | ((content: string) => string) { + if (typeof identifierOrType === 'string') { + return addJavaImportToContent(contentOrIdentifier, identifierOrType, type); + } + return (content: string) => addJavaImportToContent(content, contentOrIdentifier, identifierOrType); +} + +export type JavaAnnotation = { package?: string; annotation: string; parameters?: (oldParameters?: string) => string }; + +const addJavaAnnotationToContent = (content: string, annotationDef: JavaAnnotation) => { + const { package: packageName, annotation, parameters } = annotationDef; if (packageName) { - if (!new RegExp(`import ${packageName.replace('.', '\\.')}.${annotation};`).test(content)) { - // add the import statement just after the package statement, prettier will arrange it correctly - content = content.replace(/(package [\w.]+;\n)/, `$1import ${packageName}.${annotation};\n`); - } + content = addJavaImport(content, `${packageName}.${annotation}`); } - if (!new RegExp(`\n@${annotation}\n`).test(content)) { + const annotationToAdd = parameters ? `${annotation}(${parameters()})` : annotation; + if (!new RegExp(escapeRegExp(`\n@${annotationToAdd}\n`)).test(content)) { + if (new RegExp(escapeRegExp(`\n@${annotation}(`)).test(content)) { + throw new Error(`Annotation already exists: ${annotation} replace is not implemented yet.`); + } // add the annotation before class or interface - content = content.replace(/\n([a-w ]*(class|@?interface|enum) )/g, `\n@${annotation}\n$1`); + content = content.replace(/\n([a-w ]*(class|@?interface|enum) )/g, `\n@${annotationToAdd}\n$1`); } return content; +}; + +export function addJavaAnnotation(annotation: JavaAnnotation): (content: string) => string; +export function addJavaAnnotation(content: string, annotation: JavaAnnotation): string; +export function addJavaAnnotation( + contentOrAnnotation: string | JavaAnnotation, + annotation?: JavaAnnotation, +): string | ((content: string) => string) { + if (typeof contentOrAnnotation === 'string') { + return addJavaAnnotationToContent(contentOrAnnotation, annotation!); + } + return (content: string) => addJavaAnnotationToContent(content, contentOrAnnotation); } diff --git a/generators/java/support/generated-annotation-transform.spec.ts b/generators/java/support/generated-annotation-transform.spec.ts index 90afd4a4fa4a..6a5a44115364 100644 --- a/generators/java/support/generated-annotation-transform.spec.ts +++ b/generators/java/support/generated-annotation-transform.spec.ts @@ -15,8 +15,8 @@ interface Foo { await pipeline(Readable.from([file]), generatedAnnotationTransform('generated.by.package')); expect(file.contents.toString()).toMatchInlineSnapshot(` "package package.name; -import generated.by.package.GeneratedByJHipster; +import generated.by.package.GeneratedByJHipster; @GeneratedByJHipster interface Foo { }" @@ -34,8 +34,8 @@ interface Foo { await pipeline(Readable.from([file]), generatedAnnotationTransform('generated.by.package')); expect(file.contents.toString()).toMatchInlineSnapshot(` "package package.name; -import generated.by.package.GeneratedByJHipster; +import generated.by.package.GeneratedByJHipster; @GeneratedByJHipster @interface Foo { }" diff --git a/generators/java/support/generated-annotation-transform.ts b/generators/java/support/generated-annotation-transform.ts index 3b5974e186d1..e0680a1960b7 100644 --- a/generators/java/support/generated-annotation-transform.ts +++ b/generators/java/support/generated-annotation-transform.ts @@ -19,7 +19,7 @@ import { extname } from 'path'; import { passthrough } from '@yeoman/transform'; import { isFileStateDeleted } from 'mem-fs-editor/state'; -import addJavaAnnotation from './add-java-annotation.js'; +import { addJavaAnnotation } from './add-java-annotation.js'; const generatedAnnotationTransform = packageName => { return passthrough(file => { diff --git a/generators/java/support/index.ts b/generators/java/support/index.ts index ff28fecaf812..5b481173ca31 100644 --- a/generators/java/support/index.ts +++ b/generators/java/support/index.ts @@ -16,7 +16,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { default as addJavaAnnotation } from './add-java-annotation.js'; +export * from './add-java-annotation.js'; export * from './artifacts.js'; export * from './checks/index.js'; export * from './doc.js';