mirror of
https://github.com/divkit/divkit.git
synced 2026-05-07 20:02:32 +00:00
non_template_nested_type_not_expanded test fix
commit_hash:5855c4dac8b5229205532bb38a74e43f13c66692
This commit is contained in:
@@ -28151,7 +28151,6 @@
|
||||
"test_data/parsing_test_data/templates/reference_cascade_through_nested_usage.json":"divkit/public/test_data/parsing_test_data/templates/reference_cascade_through_nested_usage.json",
|
||||
"test_data/parsing_test_data/templates/reference_chain_two_hop_nested_in_body.json":"divkit/public/test_data/parsing_test_data/templates/reference_chain_two_hop_nested_in_body.json",
|
||||
"test_data/parsing_test_data/templates/reference_chain_two_hop_via_usage.json":"divkit/public/test_data/parsing_test_data/templates/reference_chain_two_hop_via_usage.json",
|
||||
"test_data/parsing_test_data/templates/reference_deep_bypasses_usage_literal.json":"divkit/public/test_data/parsing_test_data/templates/reference_deep_bypasses_usage_literal.json",
|
||||
"test_data/parsing_test_data/templates/reference_definition_on_leaf_template.json":"divkit/public/test_data/parsing_test_data/templates/reference_definition_on_leaf_template.json",
|
||||
"test_data/parsing_test_data/templates/reference_definition_on_usage_inside_body.json":"divkit/public/test_data/parsing_test_data/templates/reference_definition_on_usage_inside_body.json",
|
||||
"test_data/parsing_test_data/templates/reference_in_plain_nested_dict.json":"divkit/public/test_data/parsing_test_data/templates/reference_in_plain_nested_dict.json",
|
||||
|
||||
@@ -35,8 +35,7 @@ final class UntypedDivTemplateResolver {
|
||||
in: merged,
|
||||
linkSource: dictionary,
|
||||
cascadeAllowed: true,
|
||||
instanceProvidedKeys: Set(dictionary.keys),
|
||||
expanding: [templateName]
|
||||
instanceProvidedKeys: Set(dictionary.keys)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -81,8 +80,7 @@ final class UntypedDivTemplateResolver {
|
||||
in dictionary: [String: Any],
|
||||
linkSource: [String: Any]?,
|
||||
cascadeAllowed: Bool,
|
||||
instanceProvidedKeys: Set<String> = [],
|
||||
expanding: Set<String> = []
|
||||
instanceProvidedKeys: Set<String> = []
|
||||
) -> [String: Any] {
|
||||
var dict = dictionary
|
||||
var linkFieldNames = Set<String>()
|
||||
@@ -106,8 +104,7 @@ final class UntypedDivTemplateResolver {
|
||||
result[key] = resolveLinksInValue(
|
||||
value,
|
||||
linkSource: childLinkSource,
|
||||
cascadeAllowed: childCascadeAllowed,
|
||||
expanding: expanding
|
||||
cascadeAllowed: childCascadeAllowed
|
||||
)
|
||||
}
|
||||
return result
|
||||
@@ -116,47 +113,120 @@ final class UntypedDivTemplateResolver {
|
||||
private func resolveLinksInValue(
|
||||
_ value: Any,
|
||||
linkSource: [String: Any]?,
|
||||
cascadeAllowed: Bool,
|
||||
expanding: Set<String>
|
||||
cascadeAllowed: Bool
|
||||
) -> Any {
|
||||
if let dict = value as? [String: Any] {
|
||||
if cascadeAllowed,
|
||||
let linkSource,
|
||||
let type = dict["type"] as? String,
|
||||
!expanding.contains(type),
|
||||
let resolvedTemplate = resolveTemplate(named: type).value {
|
||||
var merged = resolvedTemplate
|
||||
for (key, value) in dict {
|
||||
merged[key] = value
|
||||
}
|
||||
merged["type"] = templateToType[type] ?? type
|
||||
return resolveLinks(
|
||||
in: merged,
|
||||
var parameterNames = collectParameterNames(from: resolvedTemplate)
|
||||
parameterNames.formUnion(
|
||||
collectParameterNames(from: dict, excludingKeys: parameterNames)
|
||||
)
|
||||
return resolveInstanceLinks(
|
||||
in: dict,
|
||||
linkSource: linkSource,
|
||||
cascadeAllowed: true,
|
||||
instanceProvidedKeys: Set(dict.keys),
|
||||
expanding: expanding.union([type])
|
||||
parameterNames: parameterNames
|
||||
)
|
||||
}
|
||||
return resolveLinks(
|
||||
in: dict,
|
||||
linkSource: linkSource,
|
||||
cascadeAllowed: cascadeAllowed,
|
||||
expanding: expanding
|
||||
)
|
||||
return resolveLinks(in: dict, linkSource: linkSource, cascadeAllowed: cascadeAllowed)
|
||||
}
|
||||
if let array = value as? [Any] {
|
||||
return array.map {
|
||||
resolveLinksInValue(
|
||||
$0,
|
||||
linkSource: linkSource,
|
||||
cascadeAllowed: cascadeAllowed,
|
||||
expanding: expanding
|
||||
)
|
||||
resolveLinksInValue($0, linkSource: linkSource, cascadeAllowed: cascadeAllowed)
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
private func resolveInstanceLinks(
|
||||
in dictionary: [String: Any],
|
||||
linkSource: [String: Any],
|
||||
parameterNames: Set<String>
|
||||
) -> [String: Any] {
|
||||
var dict = dictionary
|
||||
let linkKeys = dict.keys.filter { $0.hasPrefix("$") }
|
||||
for linkKey in linkKeys {
|
||||
let key = String(linkKey.dropFirst())
|
||||
guard dict[key] == nil else { continue }
|
||||
guard !parameterNames.contains(key) else { continue }
|
||||
guard let linkName = dict[linkKey] as? String else { continue }
|
||||
guard let value = linkSource[linkName] else { continue }
|
||||
dict[key] = value
|
||||
}
|
||||
|
||||
var result: [String: Any] = [:]
|
||||
for (key, value) in dict {
|
||||
guard !key.hasPrefix("$") else { continue }
|
||||
result[key] = value
|
||||
}
|
||||
|
||||
for paramName in parameterNames {
|
||||
if let value = linkSource[paramName] {
|
||||
result[paramName] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private func collectParameterNames(from dict: [String: Any]) -> Set<String> {
|
||||
var visited = Set<TemplateName>()
|
||||
return collectParameterNames(from: dict, excludingKeys: [], visited: &visited)
|
||||
}
|
||||
|
||||
private func collectParameterNames(
|
||||
from dict: [String: Any],
|
||||
excludingKeys: Set<String>
|
||||
) -> Set<String> {
|
||||
var visited = Set<TemplateName>()
|
||||
return collectParameterNames(from: dict, excludingKeys: excludingKeys, visited: &visited)
|
||||
}
|
||||
|
||||
private func collectParameterNames(
|
||||
from dict: [String: Any],
|
||||
excludingKeys: Set<String> = [],
|
||||
visited: inout Set<TemplateName>
|
||||
) -> Set<String> {
|
||||
var names = Set<String>()
|
||||
for (key, value) in dict {
|
||||
if key.hasPrefix("$"), let name = value as? String {
|
||||
names.insert(name)
|
||||
}
|
||||
guard !excludingKeys.contains(key) else { continue }
|
||||
if let nestedDict = value as? [String: Any] {
|
||||
names.formUnion(collectParameterNamesResolvingTemplates(
|
||||
from: nestedDict, visited: &visited
|
||||
))
|
||||
}
|
||||
if let array = value as? [Any] {
|
||||
for element in array {
|
||||
if let elementDict = element as? [String: Any] {
|
||||
names.formUnion(collectParameterNamesResolvingTemplates(
|
||||
from: elementDict, visited: &visited
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
private func collectParameterNamesResolvingTemplates(
|
||||
from dict: [String: Any],
|
||||
visited: inout Set<TemplateName>
|
||||
) -> Set<String> {
|
||||
if let type = dict["type"] as? String,
|
||||
!visited.contains(type),
|
||||
let resolvedTemplate = resolveTemplate(named: type).value {
|
||||
visited.insert(type)
|
||||
var names = collectParameterNames(from: dict, visited: &visited)
|
||||
names.formUnion(collectParameterNames(from: resolvedTemplate, visited: &visited))
|
||||
return names
|
||||
}
|
||||
return collectParameterNames(from: dict, visited: &visited)
|
||||
}
|
||||
}
|
||||
|
||||
private func normalizedErrors(
|
||||
|
||||
@@ -2,6 +2,9 @@
|
||||
"description": "A template name ('button') collides with the value of a 'type' field inside a non-Div nested property (accessibility.type). Verifies the resolver does not treat that non-Div dict as a template usage.",
|
||||
"templates": {
|
||||
"button": {
|
||||
"type": "text"
|
||||
},
|
||||
"content": {
|
||||
"type": "text",
|
||||
"accessibility": {
|
||||
"type": "button"
|
||||
@@ -14,7 +17,7 @@
|
||||
{
|
||||
"state_id": 0,
|
||||
"div": {
|
||||
"type": "button",
|
||||
"type": "content",
|
||||
"text": "Click me"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
{
|
||||
"description": "A template usage supplies a literal field whose name matches the source of a deep (non-top-level) reference definition inside the template body. Verifies two things simultaneously: the usage's literal is preserved on the expanded middle-level dict (it is not consumed as a formal parameter value), and the deep reference still resolves against the outer card instance rather than the usage's same-named literal (the literal does not shadow the deep reference).",
|
||||
"card": {
|
||||
"log_id": "test",
|
||||
"states": [
|
||||
{
|
||||
"state_id": 0,
|
||||
"div": {
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#f00"
|
||||
}
|
||||
],
|
||||
"type": "root"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"templates": {
|
||||
"root": {
|
||||
"type": "container",
|
||||
"items": [
|
||||
{
|
||||
"type": "nested",
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#0f0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"nested": {
|
||||
"type": "container",
|
||||
"items": [
|
||||
{
|
||||
"type": "container",
|
||||
"margins": {
|
||||
"top": 100,
|
||||
"bottom": 100,
|
||||
"left": 100,
|
||||
"right": 100
|
||||
},
|
||||
"width": {
|
||||
"type": "fixed",
|
||||
"value": 100
|
||||
},
|
||||
"height": {
|
||||
"type": "fixed",
|
||||
"value": 100
|
||||
},
|
||||
"$background": "background"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"expected": {
|
||||
"card": {
|
||||
"log_id": "test",
|
||||
"states": [
|
||||
{
|
||||
"state_id": 0,
|
||||
"div": {
|
||||
"type": "container",
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#f00"
|
||||
}
|
||||
],
|
||||
"items": [
|
||||
{
|
||||
"type": "container",
|
||||
"items": [
|
||||
{
|
||||
"type": "container",
|
||||
"margins": {
|
||||
"top": 100,
|
||||
"bottom": 100,
|
||||
"left": 100,
|
||||
"right": 100
|
||||
},
|
||||
"width": {
|
||||
"type": "fixed",
|
||||
"value": 100
|
||||
},
|
||||
"height": {
|
||||
"type": "fixed",
|
||||
"value": 100
|
||||
},
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#f00"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#0f0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user