class_docstr: Helper that visits all nodes in the AST tree and assigns .first_token and .last_token attributes
  to each of them. This is the heart of the token-marking logic.
class_docstr_tok: ["Helper","that","visits","all","nodes","in","the","AST","tree","and","assigns",".first_token","and",".last_token","attributes","to","each","of","them",".","This","is","the","heart","of","the","token-marking","logic","."]
docstr: Scan tokens in [first_token, last_token] range that are between node's children, and for any
  unmatched brackets, adjust first/last tokens to include the closing pair.
docstr_tok: ["Scan","tokens","in","[","first_token",",","last_token","]","range","that","are","between","node","'s","children",",","and","for","any","unmatched","brackets",",","adjust","first\/last","tokens","to","include","the","closing","pair","."]
code: def _expand_to_matching_pairs(self, first_token, last_token, node):
      # type: (util.Token, util.Token, AstNode) -> Tuple[util.Token, util.Token]
      """
      Scan tokens in [first_token, last_token] range that are between node's children, and for any
      unmatched brackets, adjust first/last tokens to include the closing pair.
      """
      # We look for opening parens/braces among non-child tokens (i.e. tokens between our actual
      # child nodes). If we find any closing ones, we match them to the opens.
      to_match_right = []  # type: List[Tuple[int, str]]
      to_match_left = []
      for tok in self._code.token_range(first_token, last_token):
          tok_info = tok[:2]
          if to_match_right and tok_info == to_match_right[-1]:
              to_match_right.pop()
          elif tok_info in _matching_pairs_left:
              to_match_right.append(_matching_pairs_left[tok_info])
          elif tok_info in _matching_pairs_right:
              to_match_left.append(_matching_pairs_right[tok_info])
  
      # Once done, extend `last_token` to match any unclosed parens/braces.
      for match in reversed(to_match_right):
          last = self._code.next_token(last_token)
          # Allow for trailing commas or colons (allowed in subscripts) before the closing delimiter
          while any(
              util.match_token(last, token.OP, x) for x in (",", ":")
          ):
              last = self._code.next_token(last)
          # Now check for the actual closing delimiter.
          if util.match_token(last, *match):
              last_token = last
  
      # And extend `first_token` to match any unclosed opening parens/braces.
      for match in to_match_left:
          first = self._code.prev_token(first_token)
          if util.match_token(first, *match):
              first_token = first
  
      return (first_token, last_token)
  
imports: import ast
  import numbers
  import sys
  import token
  from ast import Module
  from typing import Callable, List, Union, cast, Optional, Tuple, TYPE_CHECKING
  import six
  from .None import util
  from .asttokens import ASTTokens
  from .util import AstConstant
  from .astroid_compat import astroid_node_classes, BaseContainer
label_desc: Use image node_id 6 for calling the MarkTokens obj's underlying member method code with example usage: obj._expand_to_matching_pairs(first_token, last_token, node) and returns: first_token,  last_token