Exemplo n.º 1
0
    def has_unresolved_crossrefs(self, obj, attr_name=None):
        """
        Args:
            obj: has this object unresolved crossrefs in its fields
            (non recursively)

        Returns:
            True (has unresolved crossrefs) or False (else)
        """
        if get_model(obj) != self.model:
            return get_model(obj). \
                _tx_reference_resolver.has_unresolved_crossrefs(obj)
        else:
            for crossref_obj, attr, crossref in self.parser._crossrefs:
                if crossref_obj is obj:
                    if (not attr_name) or attr_name == attr.name:
                        return True
            return False
Exemplo n.º 2
0
def get_location(model_obj):
    """
    Args:
        model_obj: the model object of interest

    Returns:
        the line, col and filename of the model element.
        The filename may be None.
        This function may be used to fill exceptions
    """
    from textx.model import get_model
    the_model = get_model(model_obj)
    line, col = the_model._tx_parser.pos_to_linecol(model_obj._tx_position)
    return {"line": line, "col": col, "filename": the_model._tx_filename}
Exemplo n.º 3
0
    def __call__(self, parser, obj, attr, obj_ref):
        from textx.model import ObjCrossRef, get_model
        assert type(obj_ref) is ObjCrossRef, type(obj_ref)
        # cls, obj_name = obj_ref.cls, obj_ref.obj_name

        # 1) lookup URIs... (first, before looking locally - to detect file
        #    not founds and distant model errors...)
        # TODO: raise error if lookup is not unique

        model = get_model(obj)
        model_repository = model._tx_model_repository

        # 1) try to find object locally
        ret = self.scope_provider(parser, obj, attr, obj_ref)
        if ret:
            return ret

        # 2) do we have loaded models?
        for m in model_repository.local_models.filename_to_model.values():
            ret = self.scope_provider(parser, m, attr, obj_ref)
            if ret:
                return ret
        return None
Exemplo n.º 4
0
def get_metamodel(obj):
    """
    Returns metamodel of the given object's model.
    """
    return get_model(obj)._tx_metamodel
Exemplo n.º 5
0
    def resolve_one_step(self):
        """
        Resolves model references.
        """
        metamodel = self.parser.metamodel

        current_crossrefs = self.parser._crossrefs
        # print("DEBUG: Current crossrefs #: {}".
        #      format(len(current_crossrefs)))
        new_crossrefs = []
        self.delayed_crossrefs = []
        resolved_crossref_count = 0

        # -------------------------
        # start of resolve-loop
        # -------------------------
        default_scope = DefaultScopeProvider()
        for obj, attr, crossref in current_crossrefs:
            if (get_model(obj) == self.model):
                attr_value = getattr(obj, attr.name)
                attr_refs = [
                    obj.__class__.__name__ + "." + attr.name, "*." + attr.name,
                    obj.__class__.__name__ + ".*", "*.*"
                ]
                if crossref.scope_provider is not None:
                    resolved = crossref.scope_provider(obj, attr, crossref)
                else:
                    for attr_ref in attr_refs:
                        if attr_ref in metamodel.scope_providers:
                            if self.parser.debug:
                                self.parser.dprint(
                                    " FOUND {}".format(attr_ref))
                            resolved = metamodel.scope_providers[attr_ref](
                                obj, attr, crossref)
                            break
                    else:
                        resolved = default_scope(obj, attr, crossref)

                # Collect cross-references for textx-tools
                if resolved is not None and not type(resolved) is Postponed:
                    if metamodel.textx_tools_support:
                        self.pos_crossref_list.append(
                            RefRulePosition(
                                name=crossref.obj_name,
                                ref_pos_start=crossref.position,
                                ref_pos_end=crossref.position +
                                len(resolved.name),
                                def_pos_start=resolved._tx_position,
                                def_pos_end=resolved._tx_position_end))

                if resolved is None:
                    # As a fall-back search builtins if given
                    if metamodel.builtins:
                        if crossref.obj_name in metamodel.builtins:
                            from textx import textx_isinstance
                            if textx_isinstance(
                                    metamodel.builtins[crossref.obj_name],
                                    crossref.cls):
                                resolved = metamodel.builtins[
                                    crossref.obj_name]

                if resolved is None:
                    line, col = self.parser.pos_to_linecol(crossref.position)
                    raise TextXSemanticError(
                        message='Unknown object "{}" of class "{}"'.format(
                            crossref.obj_name, crossref.cls.__name__),
                        line=line,
                        col=col,
                        err_type=UNKNOWN_OBJ_ERROR,
                        expected_obj_cls=crossref.cls,
                        filename=self.model._tx_filename)

                if type(resolved) is Postponed:
                    self.delayed_crossrefs.append((obj, attr, crossref))
                    new_crossrefs.append((obj, attr, crossref))
                else:
                    resolved_crossref_count += 1
                    if attr.mult in [MULT_ONEORMORE, MULT_ZEROORMORE]:
                        attr_value.append(resolved)
                    else:
                        setattr(obj, attr.name, resolved)
            else:  # crossref not in model
                new_crossrefs.append((obj, attr, crossref))
        # -------------------------
        # end of resolve-loop
        # -------------------------
        # store cross-refs from other models in the parser list (for later
        # processing)
        self.parser._crossrefs = new_crossrefs
        # print("DEBUG: Next crossrefs #: {}".format(len(new_crossrefs)))
        return (resolved_crossref_count, self.delayed_crossrefs)