validateObjectPath method
void
validateObjectPath(
- MemberExpression node
Validates a chain of property accesses
Implementation
void validateObjectPath(MemberExpression node) {
dynamic currentObj;
String path = '';
// First get the base object
if (node.object is NameExpression) {
String objectName = (node.object as NameExpression).name.value;
validateContextExistence(objectName, node, context, isObject: true);
currentObj = context.getContextById(objectName);
path = objectName;
} else if (node.object is MemberExpression) {
// Recursively validate the nested object path
validateObjectPath(node.object as MemberExpression);
currentObj = _interpreter.getValueFromNode(node.object);
path = _interpreter.getCode(node.object);
}
// Then validate the current property access
if (currentObj != null && node.property is Name) {
String propertyName = (node.property as Name).value;
if (currentObj is Map) {
// For object literals, check if the property exists
if (!currentObj.containsKey(propertyName)) {
final availableProps = currentObj.keys.toList();
final suggestions = availableProps
.where((prop) =>
_levenshteinDistance(propertyName, prop.toString()) <= 2)
.toList();
var recovery =
'Check if you have used the correct property name (case sensitive).';
if (suggestions.isNotEmpty) {
recovery +=
'\nDid you mean one of these? ${suggestions.join(", ")}';
}
throw JSException(
node.line ?? 1,
'Property "$propertyName" does not exist on object "$path"',
detailedError:
'Code: ${_interpreter.getCode(node)}\nAvailable properties: ${availableProps.join(", ")}',
recovery: recovery,
);
}
// Update currentObj to the nested object for the next property access
currentObj = currentObj[propertyName];
} else {
// For other types of objects, use the standard property validation
validatePropertyOrMethodAccess(propertyName, path, currentObj, node);
}
}
}