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

Rewrite of the code with initial Scala 3 implementation, fixes #201 #325

Merged
merged 200 commits into from
Aug 3, 2023
Merged
Show file tree
Hide file tree
Changes from 198 commits
Commits
Show all changes
200 commits
Select commit Hold shift + click to select a range
48da17f
remove lifted transformers from the code base
krzemin Mar 7, 2023
9723a16
remove unsafe options from the code base
krzemin Mar 7, 2023
4e447e5
Remove TransformerF and enableUnsafeOption from tests and Cats module
MateuszKubuszok Mar 8, 2023
f5425f7
Remove lifted transformers and unsafe option from docs
MateuszKubuszok Mar 8, 2023
031e075
enable CI build for scala-3 branch
krzemin Mar 8, 2023
eb66b6f
remove reference to lifted transformer
krzemin Mar 8, 2023
47e5274
remove dead code
krzemin Mar 8, 2023
47488de
remove duplicated tests and dead code
krzemin Mar 8, 2023
66fd2fc
Remove lifted transformers from benchmarks
MateuszKubuszok Mar 8, 2023
ac6353a
Add Scala 3 config to build.sbt
MateuszKubuszok Mar 8, 2023
8b3f0c0
Add Scala 3 jobs to CI
MateuszKubuszok Mar 8, 2023
fde2e2c
Update sbt-welcome and fix the welcome message
MateuszKubuszok Mar 8, 2023
6942640
Small fix to logo message in sbt
MateuszKubuszok Mar 8, 2023
62d21c4
remove unused imports
krzemin Mar 8, 2023
e77c706
bring back error acc by hand benchmarks
krzemin Mar 8, 2023
4dda8eb
Fix invalid Scala 3 JS alias name
MateuszKubuszok Mar 9, 2023
ce424e4
code formatting
krzemin Mar 12, 2023
48697c3
scala-reflect and kind-projector only for Scala 2 builds
krzemin Mar 12, 2023
bb56de7
keep benchmarks only on Scala 2.13 for now
krzemin Mar 12, 2023
820358d
move code into scala-2 directories
krzemin Mar 12, 2023
e078e19
move already cross-compilable parts of the code to shared scala direc…
krzemin Mar 12, 2023
3790d6e
Port and adjust #288 to scala-3 branch (#289)
krzemin Mar 17, 2023
efd8df7
Cross compilable Scala 2/3 abstractions (#286)
MateuszKubuszok Apr 18, 2023
8f24b97
Scala 3 DSL (#290)
krzemin Apr 19, 2023
611a4d5
rebase fixup
krzemin Apr 19, 2023
c96bec9
Bump Scala 3
MateuszKubuszok Apr 19, 2023
b320510
Implement temporary new TransformerContext to old TransformerConfig c…
MateuszKubuszok Apr 20, 2023
3f8609b
Kick off rule-based architecture in new macros (#296)
MateuszKubuszok May 3, 2023
2a009db
backport #298 on scala-3 branch
krzemin May 3, 2023
cb12e43
Logging diagnostics in macros (#317)
MateuszKubuszok May 18, 2023
a5366d7
Stub Option to Option transformation rule
MateuszKubuszok May 5, 2023
0f48420
Option type unapply utility and Transformer/PartialTransformer summon…
MateuszKubuszok May 5, 2023
5c01d73
A few more utilities
MateuszKubuszok May 8, 2023
ad47e3f
Simplify structure of cakes and draft a way of deriving some expressi…
MateuszKubuszok May 19, 2023
51cba5e
Another possible API for handling freshNames
MateuszKubuszok May 23, 2023
ae77799
Prototyped fp abstractions and ExprPromise usage
MateuszKubuszok May 31, 2023
0ffc324
Migrate tests from utest to munit to make macro debugging easier
MateuszKubuszok May 31, 2023
ce35232
Fixed lambda generation, summoning excludes automatic .derive, avoid …
MateuszKubuszok Jun 1, 2023
f961b1a
Made type-class generating methods log expr with type-class rather th…
MateuszKubuszok Jun 1, 2023
726c2ef
Fixed errors with summoning and accessing private fields in macros in…
MateuszKubuszok Jun 2, 2023
db43c93
PartialOptionToNonPartial derivation rule #304, fixes to some Scala 2…
MateuszKubuszok Jun 3, 2023
c946dce
Wiring all Scala 2 Transformer DSLs to new macro architecture, tempor…
MateuszKubuszok Jun 4, 2023
e2de172
TransformToOptionRule implementation #305
MateuszKubuszok Jun 4, 2023
cabf619
AnyVal transformation implementations #307, #308, #309, refactored Ru…
MateuszKubuszok Jun 5, 2023
9b2d405
Renamed TransformerContext => TransformationContext and DerivedExpr =…
MateuszKubuszok Jun 5, 2023
aa6c5d5
Add JVM option to trace NPMs in tests, if we have a bug in macro, upg…
MateuszKubuszok Jun 5, 2023
da0f3fa
Update sbt
MateuszKubuszok Jun 5, 2023
c0212f4
Stubbed remaining derivation rules, added Type and Expr utilities for…
MateuszKubuszok Jun 6, 2023
deb02f3
More utilities for Eithers, improved utilities for constructing exprs…
MateuszKubuszok Jun 6, 2023
525954f
Refactored ComputedTypes and ComputedExprs into more generic Existent…
MateuszKubuszok Jun 6, 2023
a166b60
Implemented left.value and right.value method, fixed(?) implementatio…
MateuszKubuszok Jun 8, 2023
84070d4
Implement final part of EitherToEither rule, add utilities for liftin…
MateuszKubuszok Jun 9, 2023
208098f
MapToMap rule implementation #311, a few utilities needed to create i…
MateuszKubuszok Jun 10, 2023
9b9cba2
IterableToIterable rule implementation #312, type constructors abstra…
MateuszKubuszok Jun 11, 2023
6e86b8f
Draft product and sealed trait analysing code interface, handle annoy…
MateuszKubuszok Jun 12, 2023
833bb65
Start implementing Product and Enum utilities
MateuszKubuszok Jun 13, 2023
4c84820
Rewrite ValueClass as Existential[ValueClass[Outer, *]]
MateuszKubuszok Jun 13, 2023
3f86d5a
Drafted sealed rule concepts (need to implement pattern-matching from…
MateuszKubuszok Jun 15, 2023
f36526f
Fix 2.12 and create a few utility methods to make reading code in a f…
MateuszKubuszok Jun 15, 2023
756fe6a
Drafted code responsible for pattern matching code generation and pro…
MateuszKubuszok Jun 15, 2023
d1ee521
Drafted rough sketch of ProductToProduct rule implementation
MateuszKubuszok Jun 15, 2023
2dd0151
Rough draft of product source matching
MateuszKubuszok Jun 16, 2023
e389a06
Further prototyping Products APIs
MateuszKubuszok Jun 16, 2023
f0253fb
Small improvements to readability
MateuszKubuszok Jun 16, 2023
497dc58
Prototyped some APIs to generate optimized branch for products with m…
MateuszKubuszok Jun 17, 2023
e8b8fe8
Prototyped all APIs needed for ProductToProduct to work
MateuszKubuszok Jun 17, 2023
f17d759
Simplified ExprPromise API a bit
MateuszKubuszok Jun 17, 2023
3845805
Slightly better documentation of ProductToProduct
MateuszKubuszok Jun 17, 2023
95632f9
Make all macro versions compile (not everything implemented yet), mak…
MateuszKubuszok Jun 17, 2023
a423af2
Fill missing implementations for Scala 2 macros (not yet tested)
MateuszKubuszok Jun 17, 2023
6a95e40
First draft of ProductTypes implementations for both Scala 2 and Scala 3
MateuszKubuszok Jun 18, 2023
c2dc439
Started debuggin existing code
MateuszKubuszok Jun 18, 2023
92c53dd
More logs for debugging, get rid of filtering summoned macros in favo…
MateuszKubuszok Jun 18, 2023
ea8dc57
Align Scala 2 autoderivation with Scala 3, fix errors in ProductToPro…
MateuszKubuszok Jun 19, 2023
2370fee
Bump munit verion
MateuszKubuszok Jun 19, 2023
c9fd66f
Add prependErrorPath in ProductToProduct, create Expr.suppressUnused …
MateuszKubuszok Jun 20, 2023
c7cbcfd
Fixed default values parsing in Scala 3, allow using val/lazy vals de…
MateuszKubuszok Jun 21, 2023
7085dd6
Aligned type printing, made product errors more conforming to the Spec
MateuszKubuszok Jun 21, 2023
e116d07
Fix isPublic test in Scala 3 ProductTypes
MateuszKubuszok Jun 21, 2023
53d493a
Fix recurive calls and type unapply on Scala 2
MateuszKubuszok Jun 22, 2023
06d2f93
Comment out non-compiling tests to see the results of the compiling t…
MateuszKubuszok Jun 23, 2023
9857d21
Split product source parsing from product target parsing
MateuszKubuszok Jun 24, 2023
2c0cf29
Update dependencies
MateuszKubuszok Jun 24, 2023
3f5bd20
Split Getters and Extraction
MateuszKubuszok Jun 24, 2023
9f212b6
Prototyped more relaxed way of creating case class/Java Beans/POJOs
MateuszKubuszok Jun 24, 2023
423af7c
Simplify ProductType constructors code
MateuszKubuszok Jun 25, 2023
3be70ba
Fix error with ExprPromise.use type on Scala 3
MateuszKubuszok Jun 25, 2023
cf8ff46
Small improvements to ProductValue code
MateuszKubuszok Jun 27, 2023
f2dc4a5
Handle case objects in Scala 2 and changed Scala 2 type representation
MateuszKubuszok Jun 27, 2023
daf2dfc
Merge branch 'yolo-fix-scala-2-case-objects' into yolo-appended-proto…
MateuszKubuszok Jun 27, 2023
f8bd0d0
Bounded existential types, bounded type constructors, extractors for …
MateuszKubuszok Jun 28, 2023
aa4d60f
Transformer configs are parsed in shared code
MateuszKubuszok Jun 28, 2023
701c07b
Shortened type constructor interface name to Ctor*, moved TypeImplici…
MateuszKubuszok Jun 29, 2023
953b6fc
Fix 2.12 test compilation
MateuszKubuszok Jun 29, 2023
619f2e8
Commented out 1 test which fails to compile on Scala 3 (at earlier st…
MateuszKubuszok Jun 29, 2023
b5ca0a8
Extracted separate module for non-chimney-specific macro-shared code
MateuszKubuszok Jun 30, 2023
24b332e
Add a few lines of documentation to chimney-macro-commons
MateuszKubuszok Jun 30, 2023
8d4b23d
Add quickfix for munit compileErrors issue
jchyb Jun 23, 2023
0826ef4
Uncomment and fix many tests on Scala 2.13, ignore for now tests whic…
MateuszKubuszok Jun 30, 2023
e1013ce
Refactor SealedHierarchies to use Existential.UpperBounded, refactor …
MateuszKubuszok Jun 30, 2023
d57ec15
Fix errors path from Map to Iterable/Array
MateuszKubuszok Jun 30, 2023
55624fd
Rafactor Gateway and TransformerMacros, fix some sum types implicit e…
MateuszKubuszok Jul 1, 2023
4792379
Unignore more errors after last refactor
MateuszKubuszok Jul 1, 2023
6f3f524
Fix unreachable code errors
MateuszKubuszok Jul 1, 2023
03a0e88
fix `Internal error: unable to find the outer accessor symbol of clas…
krzemin Jul 1, 2023
6250f6f
un-ignore passing test
krzemin Jul 1, 2023
e0546ee
Remove unnecessary limitation on ToOption rule
MateuszKubuszok Jul 1, 2023
4ad1612
Implemented tuples support
MateuszKubuszok Jul 1, 2023
3c9ab77
Fixed Scala 2.12
MateuszKubuszok Jul 1, 2023
1cb01af
Check that Java Bean getters starting with is* are Boolean
MateuszKubuszok Jul 1, 2023
a13527c
Fix chimneyCats tests
MateuszKubuszok Jul 1, 2023
acfa0ca
Disable unused local check on Scala 2.12's test since @unused warning…
MateuszKubuszok Jul 2, 2023
e7fd3a6
replace size == 1 with sizeIs == 1
krzemin Jul 3, 2023
f6d6407
rename old patcher config file (to eliminate filename conflict)
krzemin Jul 3, 2023
2a58146
no fatal warnings in publishSettings
krzemin Jul 3, 2023
1f84de7
Improve error message on default-method assertion failure
MateuszKubuszok Jul 3, 2023
68b4aca
Decrease number of compilation errors on Scala 3
MateuszKubuszok Jul 3, 2023
c2a7a53
Fix error messages in JavaBeans
MateuszKubuszok Jul 3, 2023
1662fd0
.withFieldComputed on partial caches exceptions in new macros
MateuszKubuszok Jul 3, 2023
6942491
Removed a few no longer necessary TODOs, created Parallel next to App…
MateuszKubuszok Jul 3, 2023
af726dd
wip: use new transformer macros in old scala 2 patcher macros
krzemin Jul 4, 2023
35a482c
chimney exprs for patchers
krzemin Jul 4, 2023
e16c677
enableMacrosLogging in patcher dsl
krzemin Jul 4, 2023
e55439c
cross-platform patcher cfg reading
krzemin Jul 4, 2023
9899476
chimney types for patcher cfg (interface)
krzemin Jul 4, 2023
de22d48
code formatting
krzemin Jul 4, 2023
78a9c32
chimney types for patcher cfg (scala 2 platform impl)
krzemin Jul 4, 2023
39c7154
chimney types for patcher cfg (scala 3 platform impl)
krzemin Jul 4, 2023
73319a5
code formatting
krzemin Jul 4, 2023
a38c463
suppress 'Unreachable case' warnings in patcher config reading
krzemin Jul 4, 2023
5eb2e59
new patcher macro entry point, modeling patcher derivation errors
krzemin Jul 5, 2023
4e7a855
PatcherConfig in PatcherContext
krzemin Jul 5, 2023
5901af5
patchers derivation draft
krzemin Jul 5, 2023
9563513
wiring of the new patcher macros with scala 2 dsl
krzemin Jul 5, 2023
7dfb1bb
wiring patcher type class instance derivation
krzemin Jul 5, 2023
43c05ae
comment out old PatcherBlackboxMacros
krzemin Jul 5, 2023
fef8d2f
option exprs: get, isDefined
krzemin Jul 5, 2023
b35ec95
wip: patcher derivation impl
krzemin Jul 5, 2023
02d0df6
simplify code a bit
krzemin Jul 6, 2023
5f3b9ca
completed new patcher derivation logic
krzemin Jul 6, 2023
dd0220c
implement Option.orElse for scala 3
krzemin Jul 6, 2023
ba4de05
remove most of the old macro code
krzemin Jul 6, 2023
eb00fec
remove most of the old macro utils
krzemin Jul 6, 2023
8d6dcb7
remove old blackbox top-level macros
krzemin Jul 6, 2023
aa3c991
Relax rexuirements on ExistentialType.use*, add utility methods to Pr…
MateuszKubuszok Jul 6, 2023
40d8dbe
Share some utilities between Gateways
MateuszKubuszok Jul 6, 2023
5f57f3b
Move DSL-related macros to internal.compiletime.dsl, plug-in Scala 3 …
MateuszKubuszok Jul 6, 2023
cc04ee1
Move NonEmptyErrorChain and Configs to internal.runtime
MateuszKubuszok Jul 6, 2023
44351f3
Move errors to internal.compiletime
MateuszKubuszok Jul 7, 2023
4b8c158
Replaced Existential.use and ExistentialType.use with import value.Un…
MateuszKubuszok Jul 7, 2023
f5b9300
Merge branch 'master' into scala-3
MateuszKubuszok Jul 7, 2023
aaf3dd9
Test that default value is ignored and fail compilation if target has…
MateuszKubuszok Jul 8, 2023
ecb82f0
Test that Java Bean getters can be used in withFieldRenamed for renam…
MateuszKubuszok Jul 8, 2023
19accbb
Update tests to show that all withField* methods works with setters
MateuszKubuszok Jul 8, 2023
a193977
Test for not used field override
MateuszKubuszok Jul 11, 2023
a5113da
Add utilities and aliases to make ExistentialTypes shorter
MateuszKubuszok Jul 15, 2023
55c6653
Remove methods used only by macros from public API, rewrite DSL macro…
MateuszKubuszok Jul 18, 2023
55c645a
Hide DslMacroUtils
MateuszKubuszok Jul 18, 2023
0c07957
Fix paramsWithTypes for constructors and crashing genBCode phase
jchyb Jul 22, 2023
dbb1f68
Assume-out a test breaking compilation
jchyb Jul 22, 2023
68dd6ae
Fix comments after last merge
MateuszKubuszok Jul 22, 2023
5f59bd5
Better protobuf oneof support (#331)
MateuszKubuszok Jul 22, 2023
6c2569b
Standardoze Type.platformSpecific API for type calculation between Sc…
MateuszKubuszok Jul 17, 2023
b99f2ac
Improve Scala Metals work using enableBsp next to ideSkipProject
MateuszKubuszok Jul 23, 2023
bd16b00
Fix formatting
MateuszKubuszok Jul 23, 2023
795d8df
Update formater and rename Cats directory
MateuszKubuszok Jul 23, 2023
8545e25
Copy DSL documentation in chimney.dsl from Scala 2 to Scala 3
MateuszKubuszok Jul 24, 2023
e9c8e48
Add macro logging documentation to Patchers
MateuszKubuszok Jul 24, 2023
97951f0
Update formatting
MateuszKubuszok Jul 24, 2023
fec2005
Merge branch 'master' into scala-3
krzemin Jul 25, 2023
531c421
replace docs links to RTD-hosted docs
krzemin Jul 25, 2023
8e9f5c1
Merge branch 'master' into scala-3
krzemin Jul 26, 2023
13776b8
Merge branch 'master' into scala-3
MateuszKubuszok Jul 26, 2023
38065f7
Add some short explanation to why different structures exists
MateuszKubuszok Jul 26, 2023
78018f9
Sphinx documentation for 0.8 (#339)
MateuszKubuszok Jul 26, 2023
1173f42
Remove Sphinx scripts, as ReadTheDocs handles publishing for us
MateuszKubuszok Jul 28, 2023
89aebbf
Update docs' to newest Scala CLI converions, add Scala 3 mention
MateuszKubuszok Jul 28, 2023
eeb6ecb
Document reasons why something is ignored in git
MateuszKubuszok Jul 28, 2023
8a4ddf1
Test .enableMethodsAccessors/.disableMethodsAccessors the same way as…
MateuszKubuszok Jul 29, 2023
8c2ef94
Fix test name
MateuszKubuszok Jul 29, 2023
a6bf787
Add console utilities
MateuszKubuszok Jul 30, 2023
c73c5e3
Add no default values in protos docs
MateuszKubuszok Jul 30, 2023
89dc40a
Design doc
MateuszKubuszok Jul 30, 2023
5f002b2
Remove unneeded TODO
MateuszKubuszok Jul 30, 2023
c12af44
Align becnhamrk Scala version to build.sbt 2.13 version
MateuszKubuszok Jul 30, 2023
f9b3b65
Remove TODOs by providing missing explanations or checking that they …
MateuszKubuszok Jul 30, 2023
ade2455
Move PB tests to protobufs module
MateuszKubuszok Aug 1, 2023
7c0992f
Avoid using Scala 3 import syntax in PB tests
MateuszKubuszok Aug 1, 2023
6b49b80
Disable all error message checks on Scala 3
MateuszKubuszok Aug 1, 2023
06fd6d9
Another fix for Scala.js 3 in protobufs
MateuszKubuszok Aug 1, 2023
a262d6a
Add linters to Scala 3 (#337)
MateuszKubuszok Aug 2, 2023
4ae3f95
simplify generated product code for case when setters aren't used
krzemin Aug 2, 2023
551c31a
bump sbt to 1.9.3
krzemin Aug 2, 2023
dc60de0
eliminate unused warnings in Scala 3
krzemin Aug 2, 2023
66bf7e4
bring back sphinx Makefile
krzemin Aug 2, 2023
79730d5
update example in debugging macros docs
krzemin Aug 2, 2023
db0192b
readme: use newer sphinx for local docs building
krzemin Aug 2, 2023
501d758
don't override scala version for benchmarks
krzemin Aug 2, 2023
33a0498
Add Scala 3's enum specs (#347)
MateuszKubuszok Aug 3, 2023
d239264
Remove println left after debugging
MateuszKubuszok Aug 3, 2023
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
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ assignees: ''
---

**Checklist**
- [ ] I read the documentation at https://scalalandio.github.io/chimney/ and checked that the functionality exists
- [ ] I read the documentation at https://chimney.readthedocs.io/ and checked that the functionality exists
- [ ] I verified that the behavior for my use case doesn't match the documentation
- [ ] I checked the https://github.com/scalalandio/chimney/issues and haven't found the issue reported
- [ ] I confirmed that the bug is not related to functionality that was deprecated: lifted transformers (`TransformerF`s) or `unsafeOption` flags
Expand Down
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ assignees: ''
---

**Checklist**
- [ ] I read the documentation at https://scalalandio.github.io/chimney/ and checked that the functionality doesn't exists
- [ ] I read the documentation at https://chimney.readthedocs.io/ and checked that the functionality doesn't exists
- [ ] I checked the https://github.com/scalalandio/chimney/issues and haven't found the feature already requested reported
- [ ] I confirmed that the request is not related to functionality that was deprecated: lifted transformers (`TransformerF`s) or `unsafeOption` flags

Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ name: CI build

on:
push:
branches: [ master ]
branches: [ master, scala-3 ] # TODO: remove scala-3 before merging to master
pull_request:
branches: [ master ]
branches: [ master, scala-3 ] # TODO: remove scala-3 before merging to master
types: ['opened', 'reopened', 'labeled', 'synchronize']

jobs:
Expand All @@ -15,7 +15,7 @@ jobs:

strategy:
matrix:
scala: ["2_12", "2_13"]
scala: ["2_12", "2_13", "3"]
platform: ["jvm", "js", "native"]
jvm: ['adopt:1.8.0-292', 'temurin:1.19.0.2']
fail-fast: false
Expand Down Expand Up @@ -58,8 +58,8 @@ jobs:
jvm: 'temurin:1.19.0.2' # TODO LB java version from matrix
apps: sbt

- name: Run benchmarks
run: sbt "++2.13.10 benchmarks/Jmh/run -rf json -rff $(pwd)/$(git describe --tags --always).json" # TODO LB scala version from matrix
- name: Run Scala 2 benchmarks # TODO: run for Scala 3 too
run: sbt "benchmarks/Jmh/run -rf json -rff $(pwd)/$(git describe --tags --always).json"

- name: Fetch benchmarks metadata
run: curl https://raw.githubusercontent.com/scalalandio/chimney-benchmark-results/main/meta.json -o meta.json
Expand Down
19 changes: 12 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
*.class
*.log
.idea
target
# sbt build
project/project
project/target
target
*.class
# Sphinx documentation
docs/build
# Scala Metals and BSP
.bloop
.bsp
.metals
.vscode
project/metals.sbt
docs/build
.bsp
# IDEs
.idea
.vscode
# other
*.log
1 change: 1 addition & 0 deletions .jvmopts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
-XX:-OmitStackTraceInFastThrow
-XX:+UseG1GC
-Xmx2g
12 changes: 9 additions & 3 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
version = 3.5.9
version = 3.7.10
project.git = true
maxColumn = 120
runner.dialect = Scala213Source3
fileOverride {
"glob:**/src/main/scala-3/**" { runner.dialect = scala3 }
"glob:**/src/test/scala-3/**" { runner.dialect = scala3 }
}

align.preset = some

rewrite.rules = [Imports, SortModifiers]
rewrite.rules = [Imports, RedundantBraces, SortModifiers]
rewrite.imports.sort = scalastyle
rewrite.redundantBraces.stringInterpolation = true

rewrite.scala3.convertToNewSyntax = true
rewrite.scala3.removeOptionalBraces = false

docstrings.style = keep
docstrings.blankFirstLine = no
docstrings.style = SpaceAsterisk
docstrings.wrap = no

newlines.sometimesBeforeColonInMethodReturnType = true
Expand Down
5 changes: 4 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Additionally, we would like to:
* for any new feature we need a documentation:
* Scaladoc documenting: what is does, what are its type parameters, what are its value parameters
* Sphinx documentation describing new functionality
* linking Scaladoc entries to corresponding Sphinx documentation (https://scalalandio.github.io/chimney/ subpage)
* linking Scaladoc entries to corresponding Sphinx documentation (https://chimney.readthedocs.io/ subpage)
* it might be good to discuss whether put this information into a new page or as a section of an existing page

### How to start working on Chimney
Expand Down Expand Up @@ -62,3 +62,6 @@ to sbt-projectmatrix.

Some details of this setup along with useful commands you would be able to see in the welcome prompt when you start sbt
shell.

Very basic introduction can be found in [design doc](DESIGN.md). From then on we suggest looking at tests, and using
`.enableMacrosLogging` to see how some branches are triggered. If still at doubt, you can ask us on GH discussions.
201 changes: 201 additions & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Design

Before one starts looking around the codebase, there might be a few things that are useful to understand first:

* certain things are computed only by the compiler and don't exist in runtime
* some things has to be instantiated in runtime
* how DSL enable passing information to macros
* what derivation code needs to take into consideration and how it affects the infrastructure

## Runtime vs compile time

The first thing we need to understand is which part of Chimney are performed by compiler and which are executed in
the runtime. Let's look at some examples.

### Configured transformation

Let's take:

```scala
case class Foo(a: Int, b: String)
case class Bar(a: Int, b: String, c: Double)
```

```scala
Foo(1, "test").into[Bar].withFieldConst(_.c, 3.0).transform
```

The simplified version of how the code above works:

1. `.into[Bar]` wraps `Foo(1, "test")` value. The wrapper (here: `TransformerInto`) would store
**both the transformed value and possible field/coproduct value overrides**
2. these overrides are stored in `RuntimeDataStore` (currently implemented as `Vector[Any]`) -
`.withFieldConst(_.c, 3.0)` adds `3.0` as a value to this vector.
**Both wrapping and override appending would happen during runtime**, so this DLS imposes some overhead
3. the final `.transform` would generate a code similar to:
```scala
{
val transformerInto = ...
new Bar(
transformerInto.source.a,
transformerInto.source.b,
transformerInto.td.runtimDataStore(0).asInstanceOf[Double]
)
}
```
4. since there might be many overrides in `td.runtimDataStore(0)` and the macro needs to know which field override is on
which position, **DSL needs to remember somehow what each index in the vector overrides**. For that purpose there
exist `TransformerCfg`, a phantom type (a type used only in compile time) which acts as a type-level list where each
such information could be prepended. (You can think of it as of a tuple, which never get instantiated and only exist as expandable list of types). Each time user adds some override code is generated which would append a value in runtime, but also modify the type of the wrapper. Then when the macro is called it can read configuration from the type and compute which override is stored under which index.

> Types computed by `.withField*`, `.withCoproduct*`, `.enable*` and `.disable*` are intended to be inferred, not shown
> to the user and not used by the user manually. For that reason all `*Cfg` and `*Flags` are defined in `internal`
> subpackage.

Very similar thing happen when calling

```scala
Transformer.define[Foo, Bar].withFieldConst(_.c, 3.0).buildTransformer
```

1. main difference is that there is no `Foo(1, "test")` which will be wrapped, so DSL wrapper (here:
`TransformerDefinition`) passes around only `RuntimeDataStore`
2. similarly to the previous example `.with*` methods put overrides into `RuntimeDataStore` and refine the config type
by prepending type level information
3. the final result returned by `.buildTransformer` is something similar to:
```scala
{
val transformerDefinition = ...
new Transformer[Foo, Bar] {
def transform(src: Foo): Bar = new Bar(
src.a,
src.b,
transformerDefinition.runtimDataStore(0).asInstanceOf[Double]
)
}
}
```

### Automatic transformation

When calling

```scala
Bar(1, "test").transformInto[Foo]
```

**no override or flag needs to be stored in wrapper**, and the method itself summons implicit
`Transformer.AutoDerived[Bar, Foo]`. If users didn't provide their own `Transformer[Bar, Foo]` and instance will be
created by calling `Transformer.derive[Bar, Foo]`. This method doesn't require any wrapper for building something which
stores transformed value next to overrides container, so it can generate similar code:

```scala
// a.transformInto(implicit b) internally
// just calls b.transform(a)
Bar(1, "test").transformInto(
// created by implicit macro:
new Transformer.Autoderived[Bar, Foo] {
def transform(src: Bar): Foo = new Foo(
src.a,
src.b
)
}
)
```

### Partial transformation

Partial transformers works on the same principles, when it comes to what is represents in type level, what is stored in runtime, and how DSL is defined. **The true difference lies inside macros being called by the DSL**.

## DSL implementation

Macros make is relatively easy to access the value to which macro is attached. It might be very hard though to obtain the whole expression which built this value. Especially, if you consider that user could do:

```scala
val expr = Foo(1, "test").into[Bar]
if (condition)
expr.withFieldConst(_.c, 3.0).transform
else
expr.withFieldConst(_.c, 4.0).transform
```

That's why it is simpy easier to treat each modifier method as a checkpoint which would store all the added information
in the value's type.

There are actually 2 sets of configuration options that are stored by DSL in type level:

* `TransformerCfg` stores information about field and coproduct overrides, most of them is accompanied by a runtime
value (either some constant or a function)
* `TransformerFlags` store information about options which aren't tied to a particular field od subtype, so they can be
considered global - indeed there is a way for sharing these flags by all derivations in the same scope
(`TransformerConfiguration`).

In Scala 2 overrides are implemented with [whitebox macros](https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html)
which allow read which field was selected with `_.fieldName` syntax, turning it into a `String` singleton type (e.g.
`"fieldName"` type) and prepending type level information to the type (e.g.
`TransformerCfg.FieldConst["fieldName", TransformerCfg.Empty]` prepends information that 0-index in `RuntimeDataStore`
contains override for `"fieldName"` to and empty config).

In Scala 3 the mechanism is similar except whitebox macros are replaced by
[`transparent inline`](https://docs.scala-lang.org/scala3/guides/macros/inline.html#transparent-inline-methods) macros.

> DSL has a separate macro implementation for Scala 2 and 3 since there was a negligible amount of logic shared between them.

Flags, since they don't need to extract any data to generate type information, are just "normal" Scala code which
prepends flags to flag type representation.

## Derivation implementation

To understand abstractions in derivation macros some assertions need to be clarified:

* code will be cross compiled for 2.12/2.13/3 (and for JVM, Scala.js and Scala Native)
* each bugfix would have to be shared by all codebases
* the logic between all Scala versions needs to stay as similar as possible unless there are some good non-accidental
reasons to make behavior different
* the logic is already pretty complex
* DSL should not differ so that Chimney would not be a blocker for migration from one version of Scala to another
* the maintenance of this project is planned for years so one-time solution is off the table

For that reasons maintaining 2 completely distinct implementations would not be sustainable: despite an extensive test
suite there would be a lot of subtle differences in the behavior that the tests didn't catch. Instead, the decision was
made to share as much of Chimney logic between Scala 2 and Scala 3 as possible.

It has several consequences:

* the code of macros uses traits with path-dependent types and abstract methods to design shared logic - it is similar
to how Endpoints4s or Endless4s libraries are defined (the technique was described e.g. in
[C. Hofer et al. **Polymorphic Embedding of DSLs**, GPCE, 2008](https://www.informatik.uni-marburg.de/~rendel/hofer08polymorphic.pdf))
(it is much easier to understand just by looking around e.g. `Types` and `TypesPlatform` and seeing how they are used)
* most common types used are `type Type[A]` and `type Expr[A]`, defined as abstract in shared code, and specified to
concrete implementation in platform-specific code
* Scala 3 quotes depends on implicit `scala.quoted.Type` _a lot_, so shared code has to pass around types everywhere
* since only a few types can be known upfront and named: source value-type, target-type, types based one them, a lot of
types are virtually existential: types of each constructor parameter, types returned by getters, subtypes. This
requires us to express some types as existential types with values of types using these existential types. Often it's
`Type[something]` or `Expr[something]` (of both at once with the same existential type used), so certain abstractions
needed bo be designed (see `Existentials`)

Additionally, there are several implications of how code is generated:

* partial transformers attempts to avoid/delay boxing, so as many expressions as possible would try to wrap in
`partial.Result` only when absolutely unavoidable. This means that code derived for some part of partial transformer
expression doesn't have to be partial - there is a need for something modeling the same idea as `Either[Expr[A], Expr[partial.Result[A]]]` -
this resulted in `TransformationExpr[A]`
* code is derived recursively, and:
* source and target type
* location of overrides
* source value
* configurations

has to be passed around, so some `TransformationContext` of the derivation is useful to pass everything with a single
value
* macros should not fail fast, but rather aggregate all the errors making derivation impossible, so that error message
for a single macro could display all known errors at once. Instead of manually combining some `Either[List[TransformerError], TransformationExpr[A]]`
a dedicated monad comes handy - `DerivationResult` monad.
* this monad can be also used as a `Writer` monad for gathering logs, because both in Scala 2 as well in Scala 3 for
each macro only the first logging call (for each logging level: info/warn/error) would print, all the following would
be no-op. With this monad logs could be aggregated in some list and then the final message could be printed at once
(additionally, such logs can be structured).

> All of the above, are simplified explanations for why certain decisions were made and why certain utilities exists.
> Exact implementation for these utilities will change over time.
Loading
Loading