Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improvements to addJavaAnnotation #26044

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions generators/java/support/add-java-annotation.spec.ts
Original file line number Diff line number Diff line change
@@ -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 {}`);
});
});
});
});
53 changes: 46 additions & 7 deletions generators/java/support/add-java-annotation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
}"
Expand All @@ -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 {
}"
Expand Down
2 changes: 1 addition & 1 deletion generators/java/support/generated-annotation-transform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 => {
Expand Down
2 changes: 1 addition & 1 deletion generators/java/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
Loading