Skip to content

Commit fe5e16e

Browse files
veloclaude
andauthored
Scala upgrade (#1270)
* Fix Scala enumeration type generation for Scala 2.13+ compatibility - Fix ScalaEntitySerializer to handle Scala enumeration types properly - Use createSimple[Any] instead of createComparable[scala.Enumeration.Value] - Add special handling in ScalaWriter for enumeration type names - Resolves compilation errors with scala.Enumeration$Value syntax - All 96 tests now pass successfully 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Add CLAUDE.md with comprehensive project guidance 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Upgrade Scala from 2.11.12 to 2.13.16 - Update Scala version to latest 2.x release (2.13.16) - Replace deprecated JavaConversions with jdk.CollectionConverters - Add language feature flags for postfixOps and reflectiveCalls - Fix collection conversion calls to use explicit .asScala/.asJava - Fix trait inheritance issues in Paths.scala - Update test method call syntax for Scala 2.13 compatibility - 95/96 tests now passing (99% success rate) 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Fix Scala compilation warnings in querydsl-scala module - Fixed unary prefix operator definition with empty parameter list - Fixed procedure syntax deprecation warnings by adding explicit Unit return types - Added explicit type annotations to implicit definitions in Numeric and Projections - Wrapped enum identifiers in backticks for Scala 3 compatibility - Replaced unicode arrows with standard => syntax - Fixed auto-application deprecation warning 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> * Fix feature warnings and remaining deprecation warnings in querydsl-scala - Added scala.language.implicitConversions import to enable implicit conversions - Fixed remaining procedure syntax warnings by adding explicit Unit return types - Fixed auto-application deprecation warnings by adding explicit parentheses - Updated 98 test methods and utility functions across 12 test files - Resolved all feature warnings and compilation/test-compilation warnings The module now compiles cleanly with only standard Scala 2.13 library deprecation warnings remaining. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Claude <[email protected]>
1 parent 4ad4cfe commit fe5e16e

31 files changed

+399
-229
lines changed

CLAUDE.md

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
This is Querydsl, a framework for constructing type-safe SQL-like queries for multiple backends including JPA, MongoDB, and SQL in Java. This is a fork under OpenFeign maintaining the project with regular releases since the original project became stale.
8+
9+
## Build Commands
10+
11+
### Basic Build
12+
```bash
13+
./mvnw clean install
14+
```
15+
16+
### Quick Build (skip tests and checks)
17+
```bash
18+
./mvnw -Pquickbuild clean install
19+
```
20+
21+
### Profile-specific builds
22+
```bash
23+
# Build specific modules (e.g., jpa, sql, mongodb, or all)
24+
./mvnw -Pquickbuild,jpa clean install
25+
./mvnw -Pquickbuild,sql clean install
26+
./mvnw -Pquickbuild,all clean install
27+
```
28+
29+
### Test Commands
30+
```bash
31+
# Run tests without external databases
32+
./mvnw -Pno-databases verify
33+
34+
# Run CI profile tests (excludes slow tests)
35+
./mvnw -Pci verify
36+
37+
# Run development profile tests (excludes external databases and slow tests)
38+
./mvnw -Pdev verify
39+
40+
# Run specific database tests
41+
./mvnw -Pci -Dgroups=com.querydsl.core.testutil.MySQL verify
42+
./mvnw -Pci -Dgroups=com.querydsl.core.testutil.PostgreSQL verify
43+
```
44+
45+
### Code Quality
46+
```bash
47+
# Format code
48+
./mvnw -Pdev initialize
49+
50+
# Check code format
51+
./mvnw git-code-format:validate-code-format
52+
53+
# Run coverage checks
54+
./mvnw jacoco:report
55+
```
56+
57+
### Examples
58+
```bash
59+
# Build examples
60+
./mvnw -Pexamples clean install
61+
62+
# Build specific example projects
63+
cd querydsl-examples/querydsl-example-jpa-spring
64+
./mvnw clean install
65+
```
66+
67+
## Project Architecture
68+
69+
### Module Structure
70+
- **querydsl-tooling/**: Code generation and tooling modules
71+
- `querydsl-apt/`: Annotation processing tools
72+
- `querydsl-codegen/`: Code generation utilities
73+
- `querydsl-sql-codegen/`: SQL schema-based code generation
74+
- `querydsl-kotlin-codegen/`: Kotlin code generation
75+
- `querydsl-ksp-codegen/`: Kotlin Symbol Processing support
76+
- `querydsl-maven-plugin/`: Maven plugin for code generation
77+
78+
- **querydsl-libraries/**: Core library modules
79+
- `querydsl-core/`: Core query DSL framework
80+
- `querydsl-jpa/`: JPA integration with Hibernate and EclipseLink support
81+
- `querydsl-sql/`: SQL query support for various databases
82+
- `querydsl-mongodb/`: MongoDB integration
83+
- `querydsl-collections/`: In-memory collections querying
84+
- `querydsl-r2dbc/`: R2DBC reactive database support
85+
- `querydsl-spatial/`: Spatial/GIS query extensions
86+
- `querydsl-kotlin/`: Kotlin language support
87+
- `querydsl-scala/`: Scala language support
88+
89+
### Key Technologies
90+
- **Java 17+**: Main source code (tests use Java 21)
91+
- **Maven**: Build system with multi-module structure
92+
- **Annotation Processing**: Code generation via APT
93+
- **Database Support**: PostgreSQL, MySQL, Oracle, SQL Server, H2, Derby, SQLite, Firebird, CUBRID, DB2
94+
- **JPA Providers**: Hibernate, EclipseLink
95+
- **Testing**: JUnit 5, AssertJ, database containers for integration tests
96+
97+
### Code Generation Flow
98+
1. Entity classes are annotated with `@Entity` (JPA) or `@QueryEntity` (general)
99+
2. Annotation processors generate Q-classes (query types) at compile time
100+
3. Q-classes provide type-safe query construction via fluent API
101+
4. Queries are executed through backend-specific implementations
102+
103+
### Database Testing Strategy
104+
- Uses Docker Compose for integration testing with real databases
105+
- CircleCI runs parallel test jobs for each database type
106+
- Tests are categorized by database type using JUnit 5 tags
107+
- Embedded databases (H2, Derby, SQLite) for quick testing
108+
109+
## Development Profiles
110+
111+
- **no-databases**: Excludes all database-dependent tests
112+
- **ci**: Excludes slow tests and performance tests (used in CI)
113+
- **dev**: Excludes external database tests and slow tests (for local development)
114+
- **quickbuild**: Skips tests, enforcer, and documentation generation
115+
- **examples**: Includes example projects in build
116+
- **release**: Adds source/javadoc jars and GPG signing
117+
118+
## Common Tasks
119+
120+
### Adding New Database Support
121+
1. Add database driver dependency to `querydsl-sql/pom.xml`
122+
2. Create database-specific template in `querydsl-sql/src/main/resources/`
123+
3. Add keywords file in `querydsl-sql/src/main/resources/keywords/`
124+
4. Update `SQLTemplates` factory methods
125+
5. Add CircleCI job for database testing
126+
127+
### Code Generation
128+
- APT processors are in `querydsl-apt/` with separate service files for each backend
129+
- Kotlin code generation uses KSP (Kotlin Symbol Processing)
130+
- SQL codegen reads database metadata to generate Q-classes
131+
- Maven plugin provides `querydsl:export` goal for SQL codegen
132+
133+
### Testing Guidelines
134+
- Use `@Tag` annotations to categorize tests by database or performance characteristics
135+
- Integration tests should extend appropriate base classes from `querydsl-core/src/test/java/com/querydsl/`
136+
- Database-specific tests go in modules like `querydsl-jpa/src/test/java/com/querydsl/jpa/`

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@
149149
<ksp.version>2.2.0-2.0.2</ksp.version>
150150
<kotlinpoet.version>2.2.0</kotlinpoet.version>
151151
<dokka.version>2.0.0</dokka.version>
152-
<scala.version>2.11.12</scala.version>
152+
<scala.version>2.13.16</scala.version>
153153
<asm.version>9.8</asm.version>
154154
<querydsl.version>${project.version}</querydsl.version>
155155

querydsl-libraries/querydsl-scala/pom.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@
164164
<arg>-unchecked</arg>
165165
<arg>-deprecation</arg>
166166
<arg>-nobootcp</arg>
167-
<!-- <arg>-feature</arg> -->
167+
<arg>-language:postfixOps</arg>
168+
<arg>-language:reflectiveCalls</arg>
169+
<arg>-feature</arg>
168170
<!-- <arg>-explaintypes</arg> -->
169171
<!-- <arg>-verbose</arg> -->
170172
<!-- <arg>-optimise</arg> -->

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/Expressions.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import com.querydsl.core.types._
2222
import com.querydsl.scala.Constants._
2323
import com.querydsl.scala.Operations._
2424

25+
import scala.language.reflectiveCalls
26+
2527
object Constants {
2628

2729
def constant(value: Integer) = ConstantImpl.create(value.intValue)
@@ -348,7 +350,7 @@ trait NumberExpression[T] extends SimpleExpression[T] {
348350

349351
lazy val round = number[T](getType, MathOps.ROUND, this)
350352

351-
def unary_-() = negate
353+
def unary_- = negate
352354

353355
private def castToNum[A : Numeric](t: Class[A]): NumberExpression[A] = {
354356
if (t.equals(getType)) {
@@ -592,7 +594,7 @@ trait EnumExpression[T <: Enum[T]] extends ComparableExpression[T] {
592594

593595
override def as(alias: String): EnumExpression[T] = as(ExpressionUtils.path[T](getType, alias))
594596

595-
def mapToId[T <: { def id: java.lang.Long }](events: List[T]) = events groupBy (_.id.longValue) toList
597+
def mapToId[T <: { def id: java.lang.Long }](events: List[T]) = events.groupBy(_.id.longValue).toList
596598

597599
}
598600

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/GroupBy.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import scala.collection.mutable.Builder
2828
object GroupBy extends GroupBy {
2929

3030
class BuilderCollector[T,C](builder: Builder[T,C]) extends GroupCollector[T,C]{
31-
def add(o: T) { builder.+=(o) }
31+
def add(o: T): Unit = { builder.+=(o) }
3232
def get(): C = builder.result()
3333
}
3434

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/ManifestUtils.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
package com.querydsl.scala
1616

17+
import scala.language.implicitConversions
18+
1719
/**
1820
* @author tiwe
1921
*

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/Numeric.scala

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,29 +15,29 @@
1515
package com.querydsl.scala
1616

1717
object Numeric {
18-
implicit val byte = new Numeric[Byte]
19-
implicit val byte2 = new Numeric[java.lang.Byte]
20-
implicit val double = new Numeric[Double]
21-
implicit val double2 = new Numeric[java.lang.Double]
22-
implicit val float = new Numeric[Float]
23-
implicit val float2 = new Numeric[java.lang.Float]
24-
implicit val int = new Numeric[Int]
25-
implicit val int2 = new Numeric[java.lang.Integer]
26-
implicit val long = new Numeric[Long]
27-
implicit val long2 = new Numeric[java.lang.Long]
28-
implicit val short = new Numeric[Short]
29-
implicit val short2 = new Numeric[java.lang.Short]
18+
implicit val byte: Numeric[Byte] = new Numeric[Byte]
19+
implicit val byte2: Numeric[java.lang.Byte] = new Numeric[java.lang.Byte]
20+
implicit val double: Numeric[Double] = new Numeric[Double]
21+
implicit val double2: Numeric[java.lang.Double] = new Numeric[java.lang.Double]
22+
implicit val float: Numeric[Float] = new Numeric[Float]
23+
implicit val float2: Numeric[java.lang.Float] = new Numeric[java.lang.Float]
24+
implicit val int: Numeric[Int] = new Numeric[Int]
25+
implicit val int2: Numeric[java.lang.Integer] = new Numeric[java.lang.Integer]
26+
implicit val long: Numeric[Long] = new Numeric[Long]
27+
implicit val long2: Numeric[java.lang.Long] = new Numeric[java.lang.Long]
28+
implicit val short: Numeric[Short] = new Numeric[Short]
29+
implicit val short2: Numeric[java.lang.Short] = new Numeric[java.lang.Short]
3030

31-
implicit val bigDecimal = new Numeric[java.math.BigDecimal]
32-
implicit val bigInteger = new Numeric[java.math.BigInteger]
31+
implicit val bigDecimal: Numeric[java.math.BigDecimal] = new Numeric[java.math.BigDecimal]
32+
implicit val bigInteger: Numeric[java.math.BigInteger] = new Numeric[java.math.BigInteger]
3333

34-
implicit val richByte = new Numeric[scala.runtime.RichByte]
35-
implicit val richChar = new Numeric[scala.runtime.RichChar]
36-
implicit val richDouble = new Numeric[scala.runtime.RichDouble]
37-
implicit val richFloat = new Numeric[scala.runtime.RichFloat]
38-
implicit val richInt = new Numeric[scala.runtime.RichInt]
39-
implicit val richLong = new Numeric[scala.runtime.RichLong]
40-
implicit val richShort = new Numeric[scala.runtime.RichShort]
34+
implicit val richByte: Numeric[scala.runtime.RichByte] = new Numeric[scala.runtime.RichByte]
35+
implicit val richChar: Numeric[scala.runtime.RichChar] = new Numeric[scala.runtime.RichChar]
36+
implicit val richDouble: Numeric[scala.runtime.RichDouble] = new Numeric[scala.runtime.RichDouble]
37+
implicit val richFloat: Numeric[scala.runtime.RichFloat] = new Numeric[scala.runtime.RichFloat]
38+
implicit val richInt: Numeric[scala.runtime.RichInt] = new Numeric[scala.runtime.RichInt]
39+
implicit val richLong: Numeric[scala.runtime.RichLong] = new Numeric[scala.runtime.RichLong]
40+
implicit val richShort: Numeric[scala.runtime.RichShort] = new Numeric[scala.runtime.RichShort]
4141

4242
}
4343

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/Operations.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ object Operations {
6464
new OperationImpl[String](classOf[String], op, args: _*) with StringExpression
6565
}
6666

67-
def enum[T <: Enum[T]](t: Class[T], op: Op, args: Ex[_]*): EnumExpression[T] = {
67+
def `enum`[T <: Enum[T]](t: Class[T], op: Op, args: Ex[_]*): EnumExpression[T] = {
6868
new OperationImpl[T](t, op, args: _*) with EnumExpression[T]
6969
}
7070

querydsl-libraries/querydsl-scala/src/main/scala/com/querydsl/scala/Paths.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ object Paths {
6363

6464
def string(md: Metadata) = new StringPath(md)
6565

66-
def enum[T <: Enum[T]](t: Class[T], md: Metadata) = new EnumPath[T](t, md)
66+
def `enum`[T <: Enum[T]](t: Class[T], md: Metadata) = new EnumPath[T](t, md)
6767

6868
def any[T, Q <: Ex[_ >: T]](parent: Path[_], t: Class[T], q: Class[Q]): Q = create(t, q, forCollectionAny(parent))
6969

@@ -150,7 +150,7 @@ class EntityPathImpl[T](t: Class[_ <: T], md: PathMetadata)
150150
}
151151

152152
class CollectionPath[T, Q <: Ex[_ >: T]](t: Class[T], q: Class[Q], md: PathMetadata)
153-
extends PathImpl[java.util.Collection[T]](classOf[java.util.Collection[T]], md) with CollectionExpression[T,Q] {
153+
extends PathImpl[java.util.Collection[T]](classOf[java.util.Collection[T]], md) with com.querydsl.scala.CollectionExpression[T,Q] {
154154

155155
def this(t: Class[T], q: Class[Q], variable: String) = this(t, q, forVariable(variable))
156156

@@ -187,7 +187,7 @@ class ListPath[T, Q <: Ex[_ >: T]](t: Class[T], q: Class[Q], md: PathMetadata)
187187
}
188188

189189
class MapPath[K, V, Q <: Ex[_ >: V]](k: Class[K], v: Class[V], q: Class[Q], md: PathMetadata)
190-
extends PathImpl[java.util.Map[K, V]](classOf[java.util.Map[K, V]], md) with MapExpression[K, V, Q] {
190+
extends PathImpl[java.util.Map[K, V]](classOf[java.util.Map[K, V]], md) with com.querydsl.scala.MapExpression[K, V, Q] {
191191

192192
def this(k: Class[K], v: Class[V], q: Class[Q], variable: String) = this(k, v, q, forVariable(variable))
193193

0 commit comments

Comments
 (0)