diff --git a/docs/queries.md b/docs/queries.md index 2f7afe8..e73a404 100644 --- a/docs/queries.md +++ b/docs/queries.md @@ -320,6 +320,10 @@ Each configuration entry generates one final repository class in the configured `Repository`. Every named query of that entry becomes one method of that repository; sqlcj never generates a class per query. +- Every generated repository file begins with the fixed notice + `// Code generated by sqlcj. DO NOT EDIT.`, followed by one blank line and the + `package` declaration. The notice holds no version, timestamp, or filesystem + path. - The repository has one `dev.sqlcj.runtime.QueryExecutor` field and one constructor taking that executor. - Methods appear in query-source order. A method name is the lower camel form @@ -351,6 +355,8 @@ The `Author` entry of the [Quickstart](quickstart.md), which declares `DeleteAuthor`, generates one `AuthorRepository`: ```java +// Code generated by sqlcj. DO NOT EDIT. + package com.example.app.db; import dev.sqlcj.runtime.QueryExecutor; diff --git a/sqlcj-cli/src/main/java/dev/sqlcj/generator/JavaCodeGenerator.java b/sqlcj-cli/src/main/java/dev/sqlcj/generator/JavaCodeGenerator.java index c3d2d4e..ac4a0ae 100644 --- a/sqlcj-cli/src/main/java/dev/sqlcj/generator/JavaCodeGenerator.java +++ b/sqlcj-cli/src/main/java/dev/sqlcj/generator/JavaCodeGenerator.java @@ -25,6 +25,8 @@ public final class JavaCodeGenerator implements CodeGenerator { private static final String DEFAULT_PACKAGE = "generated"; + private static final String GENERATED_NOTICE = "// Code generated by sqlcj. DO NOT EDIT."; + private final TypeResolver typeResolver = new DefaultTypeResolver(); private final String packageName; @@ -71,9 +73,12 @@ private String generateSource(QueryGroupModel group, JavaNames names) { %s + %s + %s """ .formatted( + GENERATED_NOTICE, generatePackage(), generateImports(group), generateRepositoryJavaDoc(group).stripTrailing(), diff --git a/sqlcj-cli/src/test/java/dev/sqlcj/cli/command/GenerateCommandTest.java b/sqlcj-cli/src/test/java/dev/sqlcj/cli/command/GenerateCommandTest.java index cb6f8b6..138b8d7 100644 --- a/sqlcj-cli/src/test/java/dev/sqlcj/cli/command/GenerateCommandTest.java +++ b/sqlcj-cli/src/test/java/dev/sqlcj/cli/command/GenerateCommandTest.java @@ -68,7 +68,11 @@ void shouldGenerateFromConfigurationInWorkingDirectory() throws Exception { String source = Files.readString(generated); - assertTrue(source.startsWith("package dev.example.generated;")); + assertTrue( + source.startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage dev.example.generated;" + ) + ); assertTrue(source.contains("public final class UsersRepository {")); assertTrue(source.contains("public GetUserResult getUser(Long id)")); } diff --git a/sqlcj-cli/src/test/java/dev/sqlcj/compiler/SqlcjCompilerIntegrationTest.java b/sqlcj-cli/src/test/java/dev/sqlcj/compiler/SqlcjCompilerIntegrationTest.java index fffde51..ee6bbdf 100644 --- a/sqlcj-cli/src/test/java/dev/sqlcj/compiler/SqlcjCompilerIntegrationTest.java +++ b/sqlcj-cli/src/test/java/dev/sqlcj/compiler/SqlcjCompilerIntegrationTest.java @@ -1237,13 +1237,21 @@ total DECIMAL(10, 2), String users = Files.readString(usersFile); - assertTrue(users.startsWith("package dev.example.generated;")); + assertTrue( + users.startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage dev.example.generated;" + ) + ); assertTrue(users.contains("public final class UsersRepository {")); assertTrue(users.contains("public GetUserResult getUser(Long id)")); String orders = Files.readString(ordersFile); - assertTrue(orders.startsWith("package dev.example.generated;")); + assertTrue( + orders.startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage dev.example.generated;" + ) + ); assertTrue(orders.contains("public final class OrdersRepository {")); assertTrue(orders.contains("public List listOrders(LocalDateTime createdAt)")); assertTrue(orders.contains("BigDecimal total")); diff --git a/sqlcj-cli/src/test/java/dev/sqlcj/generator/JavaCodeGeneratorTest.java b/sqlcj-cli/src/test/java/dev/sqlcj/generator/JavaCodeGeneratorTest.java index 7b84b20..0b8286e 100644 --- a/sqlcj-cli/src/test/java/dev/sqlcj/generator/JavaCodeGeneratorTest.java +++ b/sqlcj-cli/src/test/java/dev/sqlcj/generator/JavaCodeGeneratorTest.java @@ -180,10 +180,43 @@ void shouldGeneratePackageDeclaration() { ); assertTrue( - file.content().startsWith("package generated;") + file.content().startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage generated;" + ) ); } + @Test + void shouldGenerateDoNotEditNoticeBeforePackageDeclaration() { + CodeGenerator generator = new JavaCodeGenerator("dev.example.generated"); + + GeneratedFile file = generate( + generator, + query( + "GetUser", + QueryType.ONE, + List.of( + new QueryParameter(1, "id", ColumnType.BIGINT) + ) + ) + ); + + String source = file.content(); + + assertTrue( + source.startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage dev.example.generated;\n" + ) + ); + + assertEquals( + 1, + source.split("// Code generated by sqlcj\\. DO NOT EDIT\\.", -1).length - 1 + ); + + assertTrue(source.contains(" * Generated by sqlcj.")); + } + @Test void shouldGenerateConfiguredPackageDeclarationAndPath() throws IOException { CodeGenerator generator = new JavaCodeGenerator("dev.example.generated"); @@ -211,7 +244,9 @@ void shouldGenerateConfiguredPackageDeclarationAndPath() throws IOException { ); assertTrue( - file.content().startsWith("package dev.example.generated;") + file.content().startsWith( + "// Code generated by sqlcj. DO NOT EDIT.\n\npackage dev.example.generated;" + ) ); assertCompiles(file);