# Copyright (c) Facebook, Inc. and its affiliates.
#
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.


"""
Data structures used for storing position information.

These are publicly exported by metadata, but their implementation lives outside of
metadata, because they're used internally by the codegen logic, which computes position
locations.
"""

from dataclasses import dataclass
from typing import Tuple, Union, cast, overload

from libcst._add_slots import add_slots


_CodePositionT = Union[Tuple[int, int], "CodePosition"]


@add_slots
@dataclass(frozen=True)
class CodePosition:
    #: Line numbers are 1-indexed.
    line: int
    #: Column numbers are 0-indexed.
    column: int


@add_slots
@dataclass(frozen=True)
class CodeRange:
    #: Starting position of a node (inclusive).
    start: CodePosition
    #: Ending position of a node (exclusive).
    end: CodePosition

    @overload
    def __init__(self, start: CodePosition, end: CodePosition) -> None:
        ...

    @overload
    def __init__(self, start: Tuple[int, int], end: Tuple[int, int]) -> None:
        ...

    # pyre-ignore[13]: Attribute `end` is never initialized.
    # pyre-ignore[13]: Attribute `start` is never initialized.
    def __init__(self, start: _CodePositionT, end: _CodePositionT) -> None:
        if isinstance(start, tuple) and isinstance(end, tuple):
            object.__setattr__(self, "start", CodePosition(start[0], start[1]))
            object.__setattr__(self, "end", CodePosition(end[0], end[1]))
        else:
            start = cast(CodePosition, start)
            end = cast(CodePosition, end)
            object.__setattr__(self, "start", start)
            object.__setattr__(self, "end", end)
