Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
440c1c8
Add proto messages with `compare_by` option
Aug 23, 2024
079cc5a
Implement a test that checks the message implements `Comparable`
Aug 23, 2024
408bf36
Implement `ComparableMessageDiscovery`
Aug 27, 2024
35fab00
Register a new module in Gradle
Aug 27, 2024
2ba1be1
Implement `ComparableMessageView`
Aug 27, 2024
25383bc
Implement `ComparableActionRenderer`
Aug 27, 2024
741ce71
Implement `ImplementComparable`
Aug 27, 2024
586c59e
Append a primitive implementation of `compareTo()` for comparable mes…
Aug 27, 2024
c99629f
Fix long lines
Aug 27, 2024
4e3b4b8
Fix the message package
Aug 27, 2024
fe93de9
Bump the version → `2.0.0-SNAPSHOT.218`
Aug 27, 2024
edc39a6
Put missing Spine annotations
Aug 27, 2024
d96a7d1
Store `file` along with type name
Aug 27, 2024
79c37e7
Propagate .proto changes to entities
Aug 27, 2024
dba9a22
Roll back to `TypeDiscovered` event
Aug 27, 2024
77a8cd1
Implement a renderer from scratch
Aug 27, 2024
26c58cd
Bump `gradle-doctor` to `0.10.0`
Aug 28, 2024
50294d3
Implement `ComparableSettings`
Aug 28, 2024
91524dd
Make comparable settings configurable from `codegen`
Aug 28, 2024
a132596
Propagate setting to the plugin model
Aug 28, 2024
5c2d3e1
Write `comparables` settings to a file
Aug 28, 2024
ef7f672
Use `TypeRenderer` for rendering
Aug 28, 2024
6c0c6dc
Test `ComparableSettings`
Aug 28, 2024
6549ba7
Test generation of implementing `Comparable`
Aug 28, 2024
d0514b8
Make the used regex expression stricter
Aug 28, 2024
8e7427e
Assert the generic parameter as well
Aug 29, 2024
3ce3e0a
Remove an empty line
Aug 30, 2024
35ce744
Enhance docs
Aug 30, 2024
d80ff09
Pick up a better name for the view
Aug 30, 2024
fba226b
Move actions to their own package
Sep 1, 2024
330683b
Extend settings with `default_comparator` map
Sep 1, 2024
409380e
Store `default_comparator` map in the view
Sep 1, 2024
01f653d
Merge remote-tracking branch 'refs/remotes/origin/master' into handle…
Sep 2, 2024
26324d0
Use `protodata.Actions` to declare actions in Proto definitions
Sep 2, 2024
07313a9
Propagate Proto changes to model
Sep 2, 2024
7db3445
Drop `ImplementComparable` action in favor of parametrized `Implement…
Sep 2, 2024
af133f1
Use a typed option
Sep 2, 2024
39c3280
Pass an empty parameter
Sep 2, 2024
51ff8c3
Restore `ImplementComparable` action
Sep 2, 2024
90367f1
Implement the first approximation of `AddComparator` action
Sep 2, 2024
b6ee64f
Test the most basic scenario
Sep 3, 2024
f26a586
Test nested field and other comparables
Sep 3, 2024
9652f9b
Implement `OptionValidator`
Sep 3, 2024
47856b2
Implement `ComparatorBuilder`
Sep 3, 2024
6ebfe70
Add more nested fields in the test data
Sep 3, 2024
ca0e634
Implement negative tests
Sep 4, 2024
5a11320
Leave a TODO for the double validation
Sep 4, 2024
94277dc
Wrap nested spec classes
Sep 4, 2024
62e65d1
Implement tests for well-known types
Sep 4, 2024
9151d92
Implement tests for nested well-known types
Sep 4, 2024
82d5aef
Bypass well-known messages during validation
Sep 4, 2024
29875d5
Implement `OptionFieldLocator`
Sep 4, 2024
8d27fb5
Move validation responsibility to `AppComparator` action
Sep 4, 2024
9f9117d
Use already created `PsiJavaFile` instance
Sep 4, 2024
0cd2f4c
Don't even try to insert an import
Sep 4, 2024
e9e52e2
Fix tests
Sep 4, 2024
8f8c084
Add an alias to enum
Sep 5, 2024
9186f67
Update docs to Proto messages
Sep 5, 2024
eddda97
Use better names for codegen content entities
Sep 5, 2024
5521958
Document codegen analysis entities
Sep 5, 2024
5e29dda
Document actions
Sep 5, 2024
c4c6fa1
Extract `MessagesLookup`
Sep 5, 2024
f6954dd
Extract an object for storing of the supported well-known types
Sep 5, 2024
0bc6677
Refactor `AddComparator` option
Sep 5, 2024
8b20542
Use FQNs
Sep 6, 2024
3d30b79
Leave a comment about `cls.addFirst()`
Sep 6, 2024
b6bea66
Remove `required` option from test fixtures
Sep 6, 2024
80bdbf1
Remove a superfluous intermediate check
Sep 6, 2024
8cbe86d
Take into account the reversed ordering
Sep 6, 2024
aa45d96
Test `AddCompareTo` action
Sep 6, 2024
540cf7b
Simplify instantiation of `ComparablePluginTestSetup`
Sep 6, 2024
911fb3d
Don't run the pipeline for each test case
Sep 6, 2024
05a9ae6
Refactor `ImplementComparableSpec`
Sep 6, 2024
f8d3935
Refactor `AddCompareToSpec`
Sep 6, 2024
522fe0f
Refactor `AddComparatorSpec`
Sep 6, 2024
7402e16
Avoid code duplication in negative test cases
Sep 6, 2024
38920ac
Bump version --> `2.0.0-SNAPSHOT.221`
Sep 6, 2024
e4d557c
Implement an integration test for `mc-java-comparable`
Sep 6, 2024
a806b02
Update reports
Sep 6, 2024
4dfccff
Fix `ComparableSettings` spec
Sep 6, 2024
5a94b01
Remove a `todo`
Sep 6, 2024
2325aa1
Remove docs repeating
Sep 6, 2024
fbd9bfe
Remove no longer used method
Sep 6, 2024
e71f5dc
Move cases with nested fields to a nested class
Sep 6, 2024
a5c6ad5
Commit IDEA metadata
Sep 6, 2024
1f9aee3
Suppress a Detekt warning
Sep 6, 2024
c867317
Actualize test case name
Sep 6, 2024
2838496
Fix formatting
Sep 6, 2024
0ba06c2
Proofread docs
Sep 6, 2024
12b2774
Remove a superfluous field from `Debtor`
Sep 6, 2024
d0c1058
Proofread docs
Sep 6, 2024
74c882e
Proofread docs
Sep 6, 2024
76460c9
Suppress `MaxLineLength` for `AddComparatorSpec`
Sep 6, 2024
e93967f
Proofread docs
Sep 6, 2024
2d3c672
Remove unused (and misplaced) import
Sep 6, 2024
081340d
Update test case name
Sep 6, 2024
e407261
Document test messages used in the integration test
Sep 6, 2024
e78184c
Document a public `reversed()` method
Sep 9, 2024
c2db03b
Shorten the parameter name
Sep 9, 2024
9c75921
Fix the proto file name
Sep 9, 2024
b332a29
Add an integration test for nested fields
Sep 9, 2024
a8c9a95
Pass the default `Any` instead of packing an `Empty`
Sep 9, 2024
c45f0d7
Extract the standard comparators to constants
Sep 9, 2024
c067937
Rename `isComparable()` to `isCompareBy()`
Sep 9, 2024
60bf3fd
Remove `String.upperCased` extension
Sep 9, 2024
f58c08a
Inline a single usage of `String.lowerCased` extension
Sep 9, 2024
d05320f
Use `lowerCamelCase()` method
Sep 9, 2024
0e347c5
Avoid the unrelated docs details when one class speaks for another
Sep 10, 2024
ffeb17c
Avoid string literals where `KClass` can be used
Sep 10, 2024
db232b9
Employ a recently-added extension from ProtoData
Sep 10, 2024
8caeebc
Bump `spine-base` to the latest version
Sep 11, 2024
cb2b7bc
Adapt validation and comparator builder to `ComparatorRegistry`
Sep 11, 2024
8636608
Implement an integration test for custom comparators
Sep 11, 2024
9feb007
Fix a typo in the import
Sep 11, 2024
390f720
Remove no longer used `Cases.kt`
Sep 11, 2024
7a22af9
Bump `spine-tool-base` to the latest version
Sep 12, 2024
eea8f84
Fix KDoc tag
Oct 4, 2024
99413d9
Merge remote-tracking branch 'refs/remotes/origin/master' into handle…
Oct 4, 2024
112598a
Remove weird import
Oct 4, 2024
e6427bf
Fix broken imports
Oct 7, 2024
b6940e2
Bump `spine-base` -> `2.0.0-SNAPSHOT.212`
Oct 7, 2024
0947b2e
Bump the version → `2.0.0-SNAPSHOT.242`
Oct 7, 2024
08fc5c6
Bump `base` -> `2.0.0-SNAPSHOT.212`
Oct 7, 2024
d023116
Rollback `base` version
Oct 7, 2024
367d9ce
Fix a test
Oct 8, 2024
9fc1944
Fix too long line
Oct 8, 2024
e80e3fe
Implement tests for dynamically-registered comparators
Oct 8, 2024
d45c437
Throw when the message is comparable and has a comparator simultaneously
Oct 8, 2024
486c13f
Mute logging
Oct 8, 2024
9297f6d
Merge branch 'refs/heads/master' into handle-comparable-option
Oct 8, 2024
9155e2d
Do not cover cyclic comparators in tests
Oct 9, 2024
14969a1
Bump the version -> `2.0.0-SNAPSHOT.244`
Oct 9, 2024
750d0e2
Merge validation and building into a single method
Oct 9, 2024
0a24ecd
Ignore the swallowed exception
Oct 9, 2024
4060ee2
Rename `SpecifiedField` to `FieldPath`
Oct 9, 2024
c132814
Introduce `ComparisonField`
Oct 9, 2024
ec8a86b
Make the builder accept ordering on the constructor
Oct 9, 2024
9ea9ae9
Refactor `AddComparator`
Oct 9, 2024
e2f6594
Extract common assertions from test cases to a function
Oct 10, 2024
af55e3b
Simplify build scripts
Oct 10, 2024
3dacc36
Proofread docs
Oct 10, 2024
cd5556d
Merge branch 'master' into handle-comparable-option
Oct 10, 2024
7748bf2
Adapt to the latest changes in `master`
Oct 10, 2024
5556b7f
Bump the version -> `2.0.0-SNAPSHOT.245`
Oct 10, 2024
3d5c17f
Update reports
Oct 10, 2024
0393f47
Fix logging
Oct 10, 2024
9add007
Use message descriptors instead of classes
Oct 11, 2024
c40319c
Bump ProtoData -> `0.61.6`
Oct 11, 2024
eb5c055
Add an empty line
Oct 11, 2024
5f740bd
Clarify the exception message
Oct 11, 2024
859f4bd
Bump `spine-core` to `2.0.0-SNAPSHOT.177` and address deprecations
Oct 11, 2024
19e4a36
Fix enum item's name
Oct 11, 2024
2c05183
Use assertions from Truth
Oct 11, 2024
35ef28d
Make error message more user-friendly
Oct 11, 2024
05a79d6
Rename `ProtoValueMessages` to `ProtobufWrapperTypes`
Oct 11, 2024
949681d
Employ a shortcut
Oct 11, 2024
8a0e320
Fix grammar
Oct 11, 2024
0a8021d
Explicitly call `runPipeline` in each spec
Oct 11, 2024
bea47dd
Use a hard `FieldPath` instead of typealias
Oct 11, 2024
a6cdbd3
Rename `ProtobufWrapperTypes` to `WellKnownComparables`
Oct 11, 2024
5171273
Move unspecific classes out of `comparable` plugin
Oct 11, 2024
55e411b
Update packaging for integration tests
Oct 11, 2024
f567ca3
Address Detekt warning
Oct 11, 2024
9427154
Update dependencies
Oct 11, 2024
abdfbb7
Move Proto field related classes to `base` package
Oct 14, 2024
608dcf8
Replace `MessageLookup` in favor of `TypeSystem`
Oct 14, 2024
61359b3
Set visual guides
Oct 14, 2024
db14147
Use `TypeSystem` in `FieldLookup`
Oct 14, 2024
f99651d
Remove `ClassLookup` in favor of an extension
Oct 14, 2024
2901dc1
Make `ComparisonField` a sealed class
Oct 14, 2024
3855ba6
Substitute `FieldLookup` with an extension function
Oct 14, 2024
9fc8b71
Actualize docs
Oct 14, 2024
457a34b
Enhance docs to `resolve()`
Oct 14, 2024
5b732f5
Proofread docs
Oct 14, 2024
5cf0fd8
Make `hasCompareByOption` a private extension
Oct 14, 2024
3ae4f9c
Rename `descending` to `reversed`
Oct 15, 2024
0f19bad
Update docs to `ComparatorBuilder.reversed`
Oct 15, 2024
44321f5
Add more checks to `TypeSystem.resolve()`
Oct 15, 2024
546f58e
Use either `proto` or `Protobuf`
Oct 15, 2024
8d19afb
Use `reference` extension
Oct 15, 2024
1118d91
Mention that the used `LocalDateTime` is not Spine-provided
Oct 15, 2024
ff787c2
Bump ProtoData -> `0.61.7`
Oct 16, 2024
b616520
Remove unnecessary non-null assertions
Oct 16, 2024
1d57415
Remove local implementation of `MessageType.javaClass()`
Oct 16, 2024
c6184c6
Extract `unsupportedFieldType()` method with enhanced diagnostic message
Oct 16, 2024
81e9f7a
Add negative test cases for `oneof` fields
Oct 16, 2024
ef9f94f
Put braces around the option name
Oct 16, 2024
c2afd1f
Update reports
Oct 16, 2024
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
3 changes: 2 additions & 1 deletion .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ object ProtoData {
* The version of ProtoData dependencies.
*/
val version: String
private const val fallbackVersion = "0.61.5"
private const val fallbackVersion = "0.61.7"

/**
* The distinct version of ProtoData used by other build tools.
Expand All @@ -82,7 +82,7 @@ object ProtoData {
* transitional dependencies, this is the version used to build the project itself.
*/
val dogfoodingVersion: String
private const val fallbackDfVersion = "0.61.5"
private const val fallbackDfVersion = "0.61.7"

/**
* The artifact for the ProtoData Gradle plugin.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ object Spine {
* @see [Spine.CoreJava.server]
* @see <a href="https://github.com/SpineEventEngine/core-java">core-java</a>
*/
const val core = "2.0.0-SNAPSHOT.176"
const val core = "2.0.0-SNAPSHOT.177"

/**
* The version of [Spine.modelCompiler].
Expand Down
1,744 changes: 1,712 additions & 32 deletions dependencies.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ import io.spine.protodata.ast.event.FileExited
import io.spine.protodata.ast.event.FileOptionDiscovered
import io.spine.server.entity.alter
import io.spine.server.entity.state
import io.spine.server.event.NoReaction
import io.spine.server.event.React
import io.spine.server.procman.ProcessManager
import io.spine.server.query.select
import io.spine.tools.mc.annotation.ApiOption.Companion.findMatching
import io.spine.tools.mc.annotation.event.fileOptionMatched
import io.spine.server.model.Nothing as NoEvents

/**
* Transforms options defined in a Protobuf file into events that match
Expand All @@ -59,23 +59,23 @@ internal class FileOptionsProcess : ProcessManager<File, FileOptions, FileOption
* values are set to `true`.
*/
@React
fun on(@External e: FileEntered): NoEvents {
fun on(@External e: FileEntered): NoReaction {
alter {
file = e.file
}
return nothing()
return noReaction()
}

@React
fun on(@External e: FileOptionDiscovered): NoEvents {
fun on(@External e: FileOptionDiscovered): NoReaction {
val isApiLevelOption = findMatching(e.option) != null
val optionValue = e.option.value
if (isApiLevelOption && optionValue.isTrue()) {
alter {
addOption(e.option)
}
}
return nothing()
return noReaction()
}

@React
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ import io.spine.protodata.ast.File
import io.spine.protodata.ast.event.FileEntered
import io.spine.protodata.java.javaMultipleFiles
import io.spine.server.entity.alter
import io.spine.server.event.NoReaction
import io.spine.server.event.React
import io.spine.server.procman.ProcessManager
import io.spine.server.procman.ProcessManagerRepository
import io.spine.server.route.EventRouting
import io.spine.tools.mc.annotation.ApiOption.Companion.findMatching
import io.spine.server.model.Nothing as NoEvents

/**
* A process manager which discovers the API annotation options set on the outer
Expand All @@ -48,7 +48,7 @@ internal class OuterClassAnnotationDiscovery:
ProcessManager<File, OuterClassAnnotations, OuterClassAnnotations.Builder>() {

@React
fun on(@External e: FileEntered): NoEvents {
fun on(@External e: FileEntered): NoReaction {
// The check here is a safety net. We should get only events for
// proto files with `java_multiple_files` set to `true`. See `Repository.setEventRouting`.
if (!e.header.javaMultipleFiles()) {
Expand All @@ -67,7 +67,7 @@ internal class OuterClassAnnotationDiscovery:
}
}
}
return nothing()
return noReaction()
}

class Repository :
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright 2024, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.tools.mc.java

import com.intellij.psi.PsiAnnotation
import io.spine.tools.java.reference
import io.spine.tools.mc.java.OverrideAnnotation.create
import io.spine.tools.psi.java.Environment.elementFactory

/**
* Creates a [PsiAnnotation] for marking overridden methods.
*
* ## Implementation note
* We do not cache the created instance of [PsiAnnotation] because PSI elements are mutable.
* We want to avoid unwanted propagation of modifications made by one renderer to others.
*
* @see create
*/
public object OverrideAnnotation {

/**
* Creates a new [PsiAnnotation] with [Override].
*/
public fun create(): PsiAnnotation {
val reference = Override::class.java.reference
val annotation = elementFactory.createAnnotationFromText("@$reference", null)
return annotation
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright 2024, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.tools.mc.java.base

import io.spine.base.FieldPath
import io.spine.base.fieldPath
import io.spine.protodata.ast.Field
import io.spine.protodata.ast.MessageType
import io.spine.protodata.ast.field
import io.spine.protodata.ast.isMessage
import io.spine.protodata.type.TypeSystem

/**
* Tells if this [FieldPath] doesn't denote a nested field.
*/
public val FieldPath.isNotNested: Boolean
get() = fieldNameList.size == 1

/**
* Returns this [FieldPath] as a single [String], where the field names
* are separated with a dot.
*
* For example, `citizen.passport.firstName`.
*/
public val FieldPath.joined: String
get() = fieldNameList.joinToString(".")

/**
* Returns the root field's name of this [FieldPath].
*
* @throws [NoSuchElementException] if the path is empty.
*/
public val FieldPath.root: String
get() = fieldNameList.first()

/**
* Resolves the given [FieldPath] against the given [MessageType] within
* this [TypeSystem].
*
* This method navigates through the nested messages and fields as specified by
* the [fieldPath], returning the final [Field] that the path points to.
*
* @param fieldPath The field path to resolve.
* @param message The message where the root of the [fieldPath] is declared.
*/
public fun TypeSystem.resolve(fieldPath: FieldPath, message: MessageType): Field {
val currentField = message.field(fieldPath.root)
if (fieldPath.isNotNested) {
return currentField
}

check(currentField.type.isMessage) {
"Can't resolve the field path `$fieldPath` because `${currentField.name}` segment " +
"doesn't denote a message. The type of this field is `${currentField.type}`. " +
"Only messages can have nested field."
}

val currentFieldMessage = currentField.type.message
val remainingFields = fieldPath.fieldNameList.drop(1)
val remainingPath = fieldPath { fieldName.addAll(remainingFields) }
val nextMessageInfo = findMessage(currentFieldMessage)

check(nextMessageInfo != null) {
"`$currentFieldMessage` was not found in the passed Proto files or their dependencies."
}

val nextMessage = nextMessageInfo.first
return resolve(remainingPath, nextMessage)
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,12 @@ public open class AddFieldClass(

private fun PsiClass.addTopLevelFieldMethods() {
type.fieldList.forEach {
val accessor = TopLevelFieldAccessor(it, fieldSupertype, typeSystem!!)
val accessor = TopLevelFieldAccessor(it, fieldSupertype, typeSystem)
addLast(accessor.method())
}
}

private fun PsiClass.addFieldClasses() {
val typeSystem = typeSystem!!
val deps = MessageTypeDependencies(type, setOf(SINGLE, ONEOF_NAME), typeSystem).asSet()
deps.forEach {
val fld = MessageTypedField(it, fieldSupertype, typeSystem)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ public class CodegenSettings @Internal public constructor(private val project: P
*/
public val uuids: UuidSettings = UuidSettings(project)

/**
* Settings for the generated code of comparable messages.
*/
public val comparables: ComparableSettings = ComparableSettings(project)

/**
* Settings for the generated validation code.
*/
Expand Down Expand Up @@ -187,6 +192,13 @@ public class CodegenSettings @Internal public constructor(private val project: P
action.execute(uuids)
}

/**
* Configures code generation for comparable messages.
*/
public fun forComparables(action: Action<ComparableSettings>) {
action.execute(comparables)
}

/**
* Configures code generation for validation messages.
*/
Expand All @@ -212,6 +224,7 @@ public class CodegenSettings @Internal public constructor(private val project: P
entities = self.entities.toProto()
validation = self.validation.toProto()
uuids = self.uuids.toProto()
comparables = self.comparables.toProto()
classpath = cp
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2024, TeamDev. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Redistribution and use in source and/or binary forms, with or without
* modification, must retain the above copyright notice and the following
* disclaimer.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

package io.spine.tools.mc.java.gradle.settings

import io.spine.tools.mc.java.settings.Comparables
import io.spine.tools.mc.java.settings.comparables
import io.spine.tools.mc.java.settings.noParameter
import org.gradle.api.Project

/**
* Code generation settings for messages that have `compare_by` option.
*/
public class ComparableSettings(project: Project) :
SettingsWithActions<Comparables>(project, DEFAULT_ACTIONS) {

override fun toProto(): Comparables = comparables {
actions = actions()
}
}

/**
* The actions applied by default to comparable messages.
*/
private val DEFAULT_ACTIONS = mapOf(
"io.spine.tools.mc.java.comparable.action.AddComparator" to noParameter,
"io.spine.tools.mc.java.comparable.action.AddCompareTo" to noParameter,
"io.spine.tools.mc.java.comparable.action.ImplementComparable" to noParameter,
)
12 changes: 12 additions & 0 deletions mc-java-base/src/main/proto/spine/tools/mc/java/settings.proto
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ message Combined {

// The classpath used to lookup types by their fully-qualified names.
tools.java.Classpath classpath = 8;

// The code generation settings for comparable messages.
Comparables comparables = 11;
}

// Configuration related to validation code.
Expand Down Expand Up @@ -227,3 +230,12 @@ message Uuids {
protodata.Actions actions = 3;
}

// Code generation settings for comparable messages.
//
// A message is comparable when it has `compare_by` option.
//
message Comparables {

// A collection of code generation actions.
protodata.Actions actions = 1;
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,6 @@ import kotlin.text.RegexOption.DOT_MATCHES_ALL
* Tells if [javaCode] contains a class which implements the given [superInterface].
*/
fun implementsInterface(javaCode: String, superInterface: Class<*>): Boolean {
val regex = Regex("""implements.*${superInterface.reference}""", DOT_MATCHES_ALL)
val regex = Regex("implements[^{}]*${superInterface.reference}[^{}]*\\{", DOT_MATCHES_ALL)
return regex.containsMatchIn(javaCode)
}
Loading