예제 #1
0
def _trace_item_layout(
    node: qlast.CreateObject,
    *,
    obj: Optional[qltracer.NamedObject] = None,
    fq_name: Optional[s_name.QualName] = None,
    ctx: LayoutTraceContext,
) -> None:
    if obj is None:
        fq_name = ctx.get_local_name(node.name)
        local_obj = ctx.objects[fq_name]
        assert isinstance(local_obj, qltracer.NamedObject)
        obj = local_obj

    assert fq_name is not None

    if isinstance(node, qlast.BasesMixin):
        bases = []
        # construct the parents set, used later in ancestors graph
        parents = set()

        for ref in _get_bases(node, ctx=ctx):
            bases.append(ref)

            # ignore std modules dependencies
            if ref.get_module_name() not in s_schema.STD_MODULES:
                parents.add(ref)

            if (
                ref.module not in ctx.local_modules
                and ref not in ctx.inh_graph
            ):
                base_obj = type(obj)(name=ref)
                ctx.inh_graph[ref] = topological.DepGraphEntry(item=base_obj)

                base = ctx.schema.get(ref)
                if isinstance(base, s_sources.Source):
                    assert isinstance(base_obj, qltracer.Source)
                    base_pointers = base.get_pointers(ctx.schema)
                    for pn, p in base_pointers.items(ctx.schema):
                        base_obj.pointers[pn] = qltracer.Pointer(
                            s_name.QualName('__', pn.name),
                            source=base,
                            target=p.get_target(ctx.schema),
                        )

        ctx.parents[fq_name] = parents
        ctx.inh_graph[fq_name] = topological.DepGraphEntry(
            item=obj,
            deps=set(bases),
            merge=set(bases),
        )

    for decl in node.commands:
        if isinstance(decl, qlast.CreateConcretePointer):
            assert isinstance(obj, qltracer.Source)
            target: Optional[qltracer.TypeLike]
            if isinstance(decl.target, qlast.TypeExpr):
                target = _resolve_type_expr(decl.target, ctx=ctx)
            else:
                target = None

            pn = s_utils.ast_ref_to_unqualname(decl.name)
            ptr = qltracer.Pointer(
                s_name.QualName('__', pn.name),
                source=obj,
                target=target,
            )
            obj.pointers[pn] = ptr
            ptr_name = s_name.QualName(
                module=fq_name.module,
                name=f'{fq_name.name}@{decl.name.name}',
            )
            ctx.objects[ptr_name] = ptr
            ctx.defdeps[fq_name].add(ptr_name)

            _trace_item_layout(
                decl, obj=ptr, fq_name=ptr_name, ctx=ctx)

        elif isinstance(decl, qlast.CreateConcreteConstraint):
            # Validate that the constraint exists at all.
            _validate_schema_ref(decl, ctx=ctx)
            _, con_fq_name = ctx.get_fq_name(decl)

            con_name = s_name.QualName(
                module=fq_name.module,
                name=f'{fq_name.name}@{con_fq_name}',
            )
            ctx.objects[con_name] = qltracer.ConcreteConstraint(con_name)
            ctx.constraints[fq_name].add(con_name)

        elif isinstance(decl, qlast.CreateAnnotationValue):
            # Validate that the constraint exists at all.
            _validate_schema_ref(decl, ctx=ctx)
예제 #2
0
def _trace_item_layout(node: qlast.CreateObject,
                       *,
                       obj=None,
                       fq_name=None,
                       ctx: LayoutTraceContext):
    if obj is None:
        fq_name = ctx.get_local_name(node.name)
        obj = ctx.objects[fq_name]

    if hasattr(node, "bases"):
        bases = []
        # construct the parents set, used later in ancestors graph
        parents = set()

        for ref in _get_bases(node, ctx=ctx):
            bases.append(ref)

            # ignore std modules dependencies
            if ref.module not in s_schema.STD_MODULES:
                parents.add(ref)

            if (ref.module not in ctx.local_modules
                    and ref not in ctx.inh_graph):
                base = ctx.schema.get(ref)
                base_obj = type(obj)(name=ref)
                for pn, p in base.get_pointers(ctx.schema).items(ctx.schema):
                    base_obj.pointers[pn] = qltracer.Pointer(
                        pn,
                        source=base,
                        target=p.get_target(ctx.schema),
                    )
                ctx.inh_graph[ref] = {
                    "item": base_obj,
                }

        ctx.parents[fq_name] = parents
        ctx.inh_graph[fq_name] = {
            "item": obj,
            "deps": bases,
            "merge": bases,
        }

    for decl in node.commands:
        if isinstance(decl, qlast.CreateConcretePointer):
            if isinstance(decl.target, qlast.TypeExpr):
                target = _resolve_type_expr(decl.target, ctx=ctx)
            else:
                target = None

            ptr = qltracer.Pointer(decl.name.name, source=obj, target=target)
            obj.pointers[decl.name.name] = ptr
            ptr_name = f'{fq_name}@{decl.name.name}'
            ctx.objects[ptr_name] = ptr
            ctx.defdeps[fq_name].add(ptr_name)

            _trace_item_layout(decl, obj=ptr, fq_name=ptr_name, ctx=ctx)

        elif isinstance(decl, qlast.CreateConcreteConstraint):
            _, con_fq_name = ctx.get_fq_name(decl)
            con_name = f'{fq_name}@{con_fq_name}'
            ctx.objects[con_name] = qltracer.ConcreteConstraint(con_name)
            ctx.constraints[fq_name].add(con_name)