-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dart: allow non-const constructible defaults to work with 'Positional…
…Defaults' (#1632) ------ Motivation ------ When fields with default values were defined in a struct and their types did not provide 'const' constructors, when such fields were used in combination with 'PositionalDefaults', then the generated code did not compile. ------ Designed solution ------ In order to be able to generate the code, which compiles when 'PositionalDefaults' annotation is used together with default values of types that do not provide const constructors, the optional values have been used. When Gluecodium encounters a type that does not provide const constructor it makes it optional in positional defaults constructor and uses null as default. Later, on initializer list it checks if user provided value different than null and if not, then initializes the field with the actual default value. This way the limitation related to const constructors is surpassed. However, if the user wants to have nullable type that does not provide const constructor and uses default value different than null, then the behavior may be surprising. Therefore, the validator was implemented for Dart to prevent users from such usage. ------ Contents of change ------ 1. New smoke and functional tests, which confirm invalid behavior. 2. Implementation of designed fix. 3. New functional tests, which confirm that the fix works as expected. 4. Validator of default values to prevent unexpected behavior + unit tests. Signed-off-by: Patryk Wrobel <[email protected]>
- Loading branch information
1 parent
2528ae3
commit eff29f1
Showing
11 changed files
with
698 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
76 changes: 76 additions & 0 deletions
76
gluecodium/src/main/java/com/here/gluecodium/generator/dart/DartDefaultValuesValidator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright (C) 2016-2024 HERE Europe B.V. | ||
* | ||
* 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 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
* License-Filename: LICENSE | ||
*/ | ||
|
||
package com.here.gluecodium.generator.dart | ||
|
||
import com.here.gluecodium.common.LimeLogger | ||
import com.here.gluecodium.model.lime.LimeAttributeType.DART | ||
import com.here.gluecodium.model.lime.LimeAttributeType.IMMUTABLE | ||
import com.here.gluecodium.model.lime.LimeAttributeValueType | ||
import com.here.gluecodium.model.lime.LimeBasicType | ||
import com.here.gluecodium.model.lime.LimeElement | ||
import com.here.gluecodium.model.lime.LimeStruct | ||
import com.here.gluecodium.model.lime.LimeValue | ||
|
||
class DartDefaultValuesValidator(private val logger: LimeLogger) { | ||
fun validate(referenceMap: Map<String, LimeElement>): Boolean { | ||
val allStructs = referenceMap.values.filterIsInstance<LimeStruct>() | ||
return !allStructs.map { validatePositionalDefaults(it) }.contains(false) | ||
} | ||
|
||
private fun validatePositionalDefaults(limeStruct: LimeStruct): Boolean { | ||
if (!limeStruct.attributes.have(DART, LimeAttributeValueType.POSITIONAL_DEFAULTS)) { | ||
return true | ||
} | ||
|
||
var result = true | ||
for (field in limeStruct.initializedFields) { | ||
// Types other than BLOB and custom LimeStructs provide const constructors. | ||
val basicType = field.typeRef.type as? LimeBasicType | ||
if (field.typeRef.type !is LimeStruct && (basicType?.typeId != LimeBasicType.TypeId.BLOB)) { | ||
continue | ||
} | ||
|
||
// Custom immutable types provide const constructors. | ||
if (field.typeRef.type.attributes.have(IMMUTABLE)) { | ||
continue | ||
} | ||
|
||
// If the type does not provide const constructor, then generated 'PositionalDefaults' constructor | ||
// will utilize optional field to avoid compilation errors. | ||
// However, if the user uses 'nullable type' and wants to set value that is different from 'null' as the | ||
// default one, then if somebody passed 'null' to the generated constructor, then it wouldn't be honored. | ||
// | ||
// Do not allow users to do that. | ||
if (field.typeRef.isNullable && field.defaultValue!! !is LimeValue.Null) { | ||
logger.error(field, "$NULLABLE_ERROR_REASON; please check $DOCS_LINK") | ||
result = false | ||
} | ||
} | ||
|
||
return result | ||
} | ||
|
||
companion object { | ||
const val NULLABLE_ERROR_REASON = | ||
"For '@PositionalDefaults' structs, nullable fields that do not provide" + | ||
" const constructors must use 'null' default value" | ||
const val DOCS_LINK = "https://github.com/heremaps/gluecodium/blob/master/docs/lime_attributes.md#dart-specific-attributes" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.