Ejemplo n.º 1
0
def format_description(annotations, scope, name):
    # description has 2 args, name and desc, store them into Name and Description separately
    resolved_name = resolve_annotation(annotations, scope + '::Name',
                                       quote(name))
    description = resolve_annotation(
        annotations, scope + '::Description',
        [resolved_name, quote('No Description')])
    if isinstance(description, str):
        description = [resolved_name, description]
    if resolved_name != quote(
            name):  # if there was a specified name, that should win
        description[0] = resolved_name
    store_annotation(annotations, scope + '::Name', description[0])
    store_annotation(annotations, scope + '::Description', description[1])
Ejemplo n.º 2
0
def fixup_class_annotations(object):
    component_menu = resolve_annotation(
        object['annotations'], 'AzClass::Edit::AppearsInAddComponentMenu')
    if component_menu:
        store_annotation(object['annotations'],
                         'AzClass::Edit::AppearsInAddComponentMenu',
                         'AZ_CRC({})'.format(component_menu))
    def apply_transformations(self, json_object):
        format_cpp_annotations(json_object)

        components = []
        nonComponents = []

        for object in json_object.get('objects', []):
            # determine serialization/reflection configuration for classes
            configure_reflection(object)
            fixup_class_annotations(object)
            format_description(object['annotations'], 'AzClass',
                               object['name'])

            # collect components/non-components
            if resolve_annotation(object['annotations'],
                                  'AzComponent') is not None:
                components.append(object)
            else:
                nonComponents.append(object)

            object['fields'] = sort_fields_by_group(object.get('fields', []))

            for field in object['fields']:
                format_description(field['annotations'], 'AzField',
                                   field['name'])

        for enum in json_object.get('enums', []):
            configure_reflection(enum)
            format_description(enum['annotations'], 'AzEnum', enum['name'])
            format_enum_values(enum)

        json_object['components'] = components
        json_object['classes'] = nonComponents
Ejemplo n.º 4
0
def sort_fields_by_group(fields):
    fields_by_group = defaultdict(list)
    for field in fields:
        group = resolve_annotation(field['annotations'], 'AzField::Group', '')
        field['group'] = group
        fields_by_group[group].append(field)
    sorted_fields = fields_by_group[""]
    for group, group_fields in fields_by_group.items():
        if group:  #ignore the default group, those come first above
            sorted_fields += group_fields
    return sorted_fields
Ejemplo n.º 5
0
def format_enum_values(enum):
    annotations = enum['annotations']
    values = resolve_annotation(annotations, 'AzEnum::Values')
    if values and 'AzEnum::Value' in values:
        values = values['AzEnum::Value']
        for value in values:
            if not value[0].startswith(enum['qualified_name']):
                value[0] = value[0].replace(enum['name'],
                                            enum['qualified_name'])
    else:
        elements = enum['elements']
        values = []
        for value in elements:
            values.append(
                [enum['qualified_name'] + '::' + value,
                 quote(value)])

    store_annotation(annotations, 'AzEnum::Values', values, True)
def configure_reflection(object):
    if object.get('type') in ('class', 'struct'):
        # look for there to either be a Serialize dict or just AzClass::Serialize(true/false)
        object['serialize'] = resolve_annotation(
            object['annotations'], 'AzClass::Serialize', False) != False
        object['reflectForEdit'] = resolve_annotation(
            object['annotations'], 'AzClass::Edit', False) != False

        serialized_fields = 0
        for field in object['fields']:
            annotations = field['annotations']
            annotations.setdefault(
                'AzField', {})  # force AzField to exist, even if it's empty
            exclude_field = resolve_annotation(
                annotations, 'AzField::Serialize',
                object['serialize']) not in (True, None)
            field['serialize'] = not exclude_field

            if field['serialize']:
                serialized_fields += 1

            # Look for edit property attributes and mark the class for editing/serialization
            field['edit'] = False
            tags_that_imply_edit = ('Edit', 'UIHandler', 'Group', 'Name',
                                    'Description')
            for tag in tags_that_imply_edit:
                if (resolve_annotation(annotations, 'AzField::' + tag)):
                    object['reflectForEdit'] = True
                    field['serialize'] = True  # edit implies serialize
                    field['edit'] = True
                    serialized_fields += 1
                    break

        # Ensure that the object is marked for serialization if fields need it
        object['serialize'] = object['serialize'] or serialized_fields > 0
    elif object.get('type') in ('enum'):
        object['serialize'] = resolve_annotation(object['annotations'],
                                                 'AzEnum') is not None
        object['reflectForEdit'] = resolve_annotation(
            object['annotations'], 'AzEnum::Values') is not None
    else:
        OutputPrint('configure_reflection: Unexpected object: {} {}'.format(
            object.get('type'), object.get('qualified_name')))
Ejemplo n.º 7
0
def configure_reflection(object):
    if object.get('type') in ('class', 'struct'):
        # look for there to either be a Serialize dict or just AzClass::Serialize(true/false)
        object['serialize'] = resolve_annotation(
            object['annotations'], 'AzClass::Serialize', False) != False
        # The field serialization default is if serialize is true and not set to opt-in
        field_serialize_default = object['serialize'] in (
            True, None, "true"
        ) and not resolve_annotation(
            object['annotations'], 'AzClass::Serialize::OptIn', False) != False

        object['reflectForEdit'] = resolve_annotation(
            object['annotations'], 'AzClass::Edit', False) != False
        # Behavior context class tags
        object['behavior'] = False
        behavior_class_tags = ('BehaviorName', )
        for tag in behavior_class_tags:
            if resolve_annotation(object['annotations'], 'AzClass::' + tag,
                                  False) != False:
                object['behavior'] = True

        # Method tags checks
        for method in object['methods']:
            # Behavior context function tags
            behavior_method_tags = ('Behavior', 'BehaviorReadOnly')
            for tag in behavior_method_tags:
                if resolve_annotation(method['annotations'],
                                      'AzFunction::' + tag, False) != False:
                    object['behavior'] = True

        # Fields tags checks
        serialized_fields = 0

        for field in object['fields']:
            annotations = field['annotations']
            annotations.setdefault(
                'AzField', {})  # force AzField to exist, even if it's empty
            # NOTE: TODO: We should exclude special fields in the actual script however AzProperty seem to NOT be used, so this is temporary till add CG support
            if 'm_azCodeGenInternal' in field['name']:
                field['serialize'] = False
            else:
                field['serialize'] = resolve_annotation(
                    annotations, 'AzField::Serialize',
                    field_serialize_default) in (True, None, "true")
                if field['serialize']:
                    serialized_fields += 1

            # Look for edit property attributes and mark the class for editing/serialization
            field['edit'] = False
            tags_that_imply_edit = ('Edit', 'ElementUIHandler', 'UIHandler',
                                    'Group', 'Name', 'Description')
            for tag in tags_that_imply_edit:
                if resolve_annotation(annotations, 'AzField::' + tag):
                    object['reflectForEdit'] = True
                    field['edit'] = True
                    # Fields not marked for Serialize need to be fixed up. Edit requires Serialize
                    if not field['serialize']:
                        OutputError(
                            '{}({}): Error: Field {} marked with tags used for Edit but not Serialize. Serialize is required for Edit features. Implicitly marking field for Serialize.'
                            .format(field['file_name'], field['line_number'],
                                    field['qualified_name']))
                        field['serialize'] = True  # edit implies serialize
                        serialized_fields += 1

            # BehaviorContext field tags
            behavior_field_tags = ('Behavior', 'BehaviorReadOnly')
            for tag in behavior_field_tags:
                if resolve_annotation(annotations, 'AzField::' + tag,
                                      False) != False:
                    object['behavior'] = True

        # Ensure that the object is marked for serialization if fields need it
        object['serialize'] = object['serialize'] or serialized_fields > 0
    elif object.get('type') in ('enum'):
        object['serialize'] = resolve_annotation(object['annotations'],
                                                 'AzEnum') is not None
        object['reflectForEdit'] = resolve_annotation(
            object['annotations'], 'AzEnum::Values') is not None
        if resolve_annotation(object['annotations'], 'AzEnum::Behavior',
                              False) != False:
            object['behavior'] = True
    else:
        OutputPrint('configure_reflection: Unexpected object: {} {}'.format(
            object.get('type'), object.get('qualified_name')))
    # determine of the object needs Reflection function.
    if object['serialize'] or object['behavior'] or resolve_annotation(
            object['annotations'], 'AzClass::CustomReflection', False):
        object['hasReflection'] = True
    else:
        object['hasReflection'] = False