Skip to content

[python] TokenStreamRewriter _reduceToSingleOperationPerIndex error when reducing mixture of Replace and Insert operations #4818

Description

@Carl-Major

Description

The Python TokenStreamRewriter class has a bug when there's a mixture of both Replace and Insert operations queued up, and some of the Insert operations overlap. The "Walk inserts" section of _reduceToSingleOperationPerIndex uses the wrong index when combining Inserts, which risks setting the wrong operation to None.

To Reproduce

  1. Define a list of rewrites which has a Replace, then two Inserts which overlap. Eg [ReplaceOp(tokens, 2, 4, "foo"), InsertBeforeOp(tokens, 6, "bar"), InsertBeforeOp(tokens, 6, "baz")]
  2. Try call _reduceToSingleOperationPerIndex (either directly in a unit test, or by calling getText()
    • Expected behaviour: should combine the Insert operations and leave the ReplaceOp untouched, leaving: [ReplaceOp(tokens, 2, 4, "foo"), None, InsertBeforeOp(tokens, 6, "bazbar")]
    • Actual behaviour: Incorrectly sets the ReplaceOp to None because the Index reference is wrong, leaving: [None, InsertBeforeOp(tokens, 6, "bar"), InsertBeforeOp(tokens, 6, "baz")]
  3. It then fails with a ValueError because two different operations are still defined for the same index, 6.

Suggested Fix

The "# Walk Replaces" section of the same method is already solving this issue by referencing .instructionIndex. I suspect that Inserts don't do the same is an oversight. So I'd suggest implementing the same approach for Inserts checks as well:

  1. Change both line 177 and line 180:
    • from: rewrites[prev_index] = None
    • to: rewrites[prevIop.instructionIndex] = None
  2. After that change, prev_index is no longer needed anywhere, so we can remove the enumerate call and change line 174:
    • from: for prev_index, prevIop in enumerate(prevInserts):
    • to: for prevIop in prevInserts: (this is same code as the Walk Replace section)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions