tagan.validation-impl.1.5.1.source-code.validation.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of validation-impl Show documentation
Show all versions of validation-impl Show documentation
Yatagan is a Dependency Injection framework, specializing on runtime performance and build speed. Supports code generation (apt/kapt/ksp) or reflection.
The newest version!
/*
* Copyright 2022 Yandex LLC
*
* 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.
*/
package com.yandex.yatagan.validation.impl
import com.yandex.yatagan.base.traverseDepthFirstWithPath
import com.yandex.yatagan.base.zipWithNextOrNull
import com.yandex.yatagan.core.model.ClassBackedModel
import com.yandex.yatagan.lang.Type
import com.yandex.yatagan.validation.LocatedMessage
import com.yandex.yatagan.validation.MayBeInvalid
import com.yandex.yatagan.validation.ValidationMessage
import com.yandex.yatagan.validation.Validator
import com.yandex.yatagan.validation.format.Strings
import com.yandex.yatagan.validation.format.reportError
import kotlin.LazyThreadSafetyMode.NONE
private class ValidatorImpl : Validator {
private val _children = arrayListOf()
val children: List
get() = _children
private val _messages = lazy(NONE) { arrayListOf() }
val messages: List
get() = if (_messages.isInitialized()) _messages.value else emptyList()
override fun report(message: ValidationMessage) {
_messages.value += message
}
override fun child(node: MayBeInvalid) {
_children += node
}
override fun inline(node: MayBeInvalid) {
if (node is ClassBackedModel) {
val type = node.type
// A uniform mechanism of reporting unresolved types.
if (type.isInvalid()) {
reportError(Strings.Errors.invalidType(type)) {
if ("unresolved-type-var" in type.toString()) {
addNote(Strings.Notes.unresolvedTypeVar())
} else {
addNote(Strings.Notes.whyTypeCanBeUnresolved())
}
}
}
}
node.validate(this)
}
}
fun validate(
root: MayBeInvalid,
): Collection {
val cache = hashMapOf()
val result: MutableMap>> = mutableMapOf()
traverseDepthFirstWithPath(
roots = listOf(root),
childrenOf = { cache[it]?.children ?: emptyList() },
visit = { path, node ->
val validator = cache.getOrPut(node) {
ValidatorImpl().also { validator -> validator.inline(node) }
}
for (message in validator.messages) {
// Extract current path from stack::substack
result.getOrPut(message, ::mutableSetOf) += path.toList()
}
}
)
return result.map { (message, paths) ->
val pathStrings: MutableList> = paths.mapTo(arrayListOf()) { path: List ->
path.zipWithNextOrNull { node: MayBeInvalid, itsChild: MayBeInvalid? ->
node.toString(childContext = itsChild)
}
}
pathStrings.sortWith(PathComparator)
LocatedMessage(
message = object : ValidationMessage by message {
override val notes: Collection = message.notes.sortedWith(CharSequenceComparator)
},
encounterPaths = pathStrings,
)
}
}
private fun Type.isInvalid(): Boolean {
return isUnresolved || typeArguments.any(Type::isInvalid)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy