Пример #1
0
    def computeStatement(self, constraint_collection):
        # This node has many children to handle, pylint: disable=R0912,R0914,R0915
        tried = self.getBlockTry()

        except_handler = self.getBlockExceptHandler()
        break_handler = self.getBlockBreakHandler()
        continue_handler = self.getBlockContinueHandler()
        return_handler = self.getBlockReturnHandler()

        # The tried block must be considered as a branch, if it is not empty
        # already.
        collection_start = ConstraintCollectionBranch(
            parent = constraint_collection,
            name   = "try start"
        )

        abort_context = constraint_collection.makeAbortStackContext(
            catch_breaks    = break_handler is not None,
            catch_continues = continue_handler is not None,
            catch_returns   = return_handler is not None
        )

        with abort_context:
            # As a branch point for the many types of handlers.

            result = tried.computeStatementsSequence(
                constraint_collection = constraint_collection
            )

            # We might be done entirely already.
            if result is None:
                return None, "new_statements", "Removed now empty try statement."

            # Might be changed.
            if result is not tried:
                self.setBlockTry(result)
                tried = result

            break_collections = constraint_collection.getLoopBreakCollections()
            continue_collections = constraint_collection.getLoopContinueCollections()
            return_collections = constraint_collection.getFunctionReturnCollections()

        tried_may_raise = tried.mayRaiseException(BaseException)
        # Exception handling is useless if no exception is to be raised.
        # TODO: signal the change.
        if not tried_may_raise:
            if except_handler is not None:
                self.setBlockExceptHandler(None)
                except_handler = None

        # If tried may raise, even empty exception handler has a meaning to
        # ignore that exception.
        if tried_may_raise:
            collection_exception_handling = ConstraintCollectionBranch(
                parent = collection_start,
                name   = "except handler"
            )

            collection_exception_handling.degradePartiallyFromTriedCode(tried)

            if except_handler is not None:
                result = except_handler.computeStatementsSequence(
                    constraint_collection = collection_exception_handling
                )

                # Might be changed.
                if result is not except_handler:
                    self.setBlockExceptHandler(result)
                    except_handler = result

        if break_handler is not None:
            if not tried.mayBreak():
                self.setBlockBreakHandler(None)
                break_handler = None

        if break_handler is not None:
            collection_break = ConstraintCollectionBranch(
                parent = collection_start,
                name   = "break handler"
            )

            collection_break.mergeMultipleBranches(break_collections)

            result = break_handler.computeStatementsSequence(
                constraint_collection = collection_break
            )

            # Might be changed.
            if result is not break_handler:
                self.setBlockBreakHandler(result)
                break_handler = result

        if continue_handler is not None:
            if not tried.mayContinue():
                self.setBlockContinueHandler(None)
                continue_handler = None

        if continue_handler is not None:
            collection_continue = ConstraintCollectionBranch(
                parent = collection_start,
                name   = "continue handler"
            )

            collection_continue.mergeMultipleBranches(continue_collections)

            result = continue_handler.computeStatementsSequence(
                constraint_collection = collection_continue
            )

            # Might be changed.
            if result is not continue_handler:
                self.setBlockContinueHandler(result)
                continue_handler = result

        if return_handler is not None:
            if not tried.mayReturn():
                self.setBlockReturnHandler(None)
                return_handler = None

        if return_handler is not None:
            collection_return = ConstraintCollectionBranch(
                parent = collection_start,
                name   = "return handler"
            )

            collection_return.mergeMultipleBranches(return_collections)

            result = return_handler.computeStatementsSequence(
                constraint_collection = collection_return
            )

            # Might be changed.
            if result is not return_handler:
                self.setBlockReturnHandler(result)
                return_handler = result

        if return_handler is not None:
            if return_handler.getStatements()[0].isStatementReturn() and \
               return_handler.getStatements()[0].getExpression().isExpressionReturnedValueRef():
                self.setBlockReturnHandler(None)
                return_handler = None


        # Merge exception handler only if it is used. Empty means it is not
        # aborting, as it swallows the exception.
        if tried_may_raise and (
               except_handler is None or \
               not except_handler.isStatementAborting()
            ):
            constraint_collection.mergeBranches(
                collection_yes = collection_exception_handling,
                collection_no  = None
            )

        # An empty exception handler means we have to swallow exception.
        if not tried_may_raise and \
           break_handler is None and \
           continue_handler is None and \
           return_handler is None:
            return tried, "new_statements", "Removed all try handlers."

        tried_statements = tried.getStatements()

        pre_statements = []

        while tried_statements:
            tried_statement = tried_statements[0]

            if tried_statement.mayRaiseException(BaseException):
                break

            if break_handler is not None and \
               tried_statement.mayBreak():
                break

            if continue_handler is not None and \
               tried_statement.mayContinue():
                break

            if return_handler is not None and \
               tried_statement.mayReturn():
                break

            pre_statements.append(tried_statement)
            tried_statements = list(tried_statements)

            del tried_statements[0]

        post_statements = []

        if except_handler is not None and except_handler.isStatementAborting():
            while tried_statements:
                tried_statement = tried_statements[-1]

                if tried_statement.mayRaiseException(BaseException):
                    break

                if break_handler is not None and \
                   tried_statement.mayBreak():
                    break

                if continue_handler is not None and \
                   tried_statement.mayContinue():
                    break

                if return_handler is not None and \
                   tried_statement.mayReturn():
                    break

                post_statements.insert(0, tried_statement)
                tried_statements = list(tried_statements)

                del tried_statements[-1]

        if pre_statements or post_statements:
            assert tried_statements # Should be dealt with already

            tried.setStatements(tried_statements)

            result = StatementsSequence(
                statements = pre_statements + [self] + post_statements,
                source_ref = self.getSourceReference()
            )

            # TODO: We probably don't want to say this for re-formulation ones.
            return result, "new_statements", "Reduced scope of tried block."

        return self, None, None
Пример #2
0
    def computeStatement(self, constraint_collection):
        # This node has many children to handle, pylint: disable=R0912,R0914
        tried = self.getBlockTry()

        except_handler = self.getBlockExceptHandler()
        break_handler = self.getBlockBreakHandler()
        continue_handler = self.getBlockContinueHandler()
        return_handler = self.getBlockReturnHandler()

        # The tried block must be considered as a branch, if it is not empty
        # already.
        collection_start = ConstraintCollectionBranch(
            parent=constraint_collection, name="try start")

        abort_context = constraint_collection.makeAbortStackContext(
            catch_breaks=break_handler is not None,
            catch_continues=continue_handler is not None,
            catch_returns=return_handler is not None,
            catch_exceptions=True,
        )

        with abort_context:
            # As a branch point for the many types of handlers.

            result = tried.computeStatementsSequence(
                constraint_collection=constraint_collection)

            # We might be done entirely already.
            if result is None:
                return None, "new_statements", "Removed now empty try statement."

            # Might be changed.
            if result is not tried:
                self.setBlockTry(result)
                tried = result

            break_collections = constraint_collection.getLoopBreakCollections()
            continue_collections = constraint_collection.getLoopContinueCollections(
            )
            return_collections = constraint_collection.getFunctionReturnCollections(
            )
            exception_collections = constraint_collection.getExceptionRaiseCollections(
            )

        tried_may_raise = tried.mayRaiseException(BaseException)
        # Exception handling is useless if no exception is to be raised.
        # TODO: signal the change.
        if not tried_may_raise:
            if except_handler is not None:
                self.setBlockExceptHandler(None)
                except_handler = None

        # If tried may raise, even empty exception handler has a meaning to
        # ignore that exception.
        if tried_may_raise:
            collection_exception_handling = ConstraintCollectionBranch(
                parent=collection_start, name="except handler")

            if not exception_collections:
                for statement in tried.getStatements():
                    if statement.mayRaiseException(BaseException):
                        assert False, statement.asXmlText()

                assert False

            collection_exception_handling.mergeMultipleBranches(
                exception_collections)

            if except_handler is not None:
                result = except_handler.computeStatementsSequence(
                    constraint_collection=collection_exception_handling)

                # Might be changed.
                if result is not except_handler:
                    self.setBlockExceptHandler(result)
                    except_handler = result

        if break_handler is not None:
            if not tried.mayBreak():
                self.setBlockBreakHandler(None)
                break_handler = None

        if break_handler is not None:
            collection_break = ConstraintCollectionBranch(
                parent=collection_start, name="break handler")

            collection_break.mergeMultipleBranches(break_collections)

            result = break_handler.computeStatementsSequence(
                constraint_collection=collection_break)

            # Might be changed.
            if result is not break_handler:
                self.setBlockBreakHandler(result)
                break_handler = result

        if continue_handler is not None:
            if not tried.mayContinue():
                self.setBlockContinueHandler(None)
                continue_handler = None

        if continue_handler is not None:
            collection_continue = ConstraintCollectionBranch(
                parent=collection_start, name="continue handler")

            collection_continue.mergeMultipleBranches(continue_collections)

            result = continue_handler.computeStatementsSequence(
                constraint_collection=collection_continue)

            # Might be changed.
            if result is not continue_handler:
                self.setBlockContinueHandler(result)
                continue_handler = result

        if return_handler is not None:
            if not tried.mayReturn():
                self.setBlockReturnHandler(None)
                return_handler = None

        if return_handler is not None:
            collection_return = ConstraintCollectionBranch(
                parent=collection_start, name="return handler")

            collection_return.mergeMultipleBranches(return_collections)

            result = return_handler.computeStatementsSequence(
                constraint_collection=collection_return)

            # Might be changed.
            if result is not return_handler:
                self.setBlockReturnHandler(result)
                return_handler = result

        if return_handler is not None:
            if return_handler.getStatements()[0].isStatementReturn() and \
               return_handler.getStatements()[0].getExpression().isExpressionReturnedValueRef():
                self.setBlockReturnHandler(None)
                return_handler = None

        # Merge exception handler only if it is used. Empty means it is not
        # aborting, as it swallows the exception.
        if tried_may_raise and (
               except_handler is None or \
               not except_handler.isStatementAborting()
            ):
            constraint_collection.mergeBranches(
                collection_yes=collection_exception_handling,
                collection_no=None)

        # An empty exception handler means we have to swallow exception.
        if not tried_may_raise and \
           break_handler is None and \
           continue_handler is None and \
           return_handler is None:
            return tried, "new_statements", "Removed all try handlers."

        tried_statements = tried.getStatements()

        pre_statements = []

        while tried_statements:
            tried_statement = tried_statements[0]

            if tried_statement.mayRaiseException(BaseException):
                break

            if break_handler is not None and \
               tried_statement.mayBreak():
                break

            if continue_handler is not None and \
               tried_statement.mayContinue():
                break

            if return_handler is not None and \
               tried_statement.mayReturn():
                break

            pre_statements.append(tried_statement)
            tried_statements = list(tried_statements)

            del tried_statements[0]

        post_statements = []

        if except_handler is not None and except_handler.isStatementAborting():
            while tried_statements:
                tried_statement = tried_statements[-1]

                if tried_statement.mayRaiseException(BaseException):
                    break

                if break_handler is not None and \
                   tried_statement.mayBreak():
                    break

                if continue_handler is not None and \
                   tried_statement.mayContinue():
                    break

                if return_handler is not None and \
                   tried_statement.mayReturn():
                    break

                post_statements.insert(0, tried_statement)
                tried_statements = list(tried_statements)

                del tried_statements[-1]

        if pre_statements or post_statements:
            assert tried_statements  # Should be dealt with already

            tried.setStatements(tried_statements)

            result = StatementsSequence(statements=pre_statements + [self] +
                                        post_statements,
                                        source_ref=self.getSourceReference())

            def explain():
                # TODO: We probably don't want to say this for re-formulation ones.
                result = "Reduced scope of tried block."

                if pre_statements:
                    result += " Leading statements at %s." % (','.join(
                        x.getSourceReference().getAsString() + '/' + str(x)
                        for x in pre_statements))

                if post_statements:
                    result += " Trailing statements at %s." % (','.join(
                        x.getSourceReference().getAsString() + '/' + str(x)
                        for x in post_statements))

                return result

            return (result, "new_statements", explain)

        return self, None, None