"""
This type stub file was generated by pyright.
"""

from abc import abstractmethod
from collections.abc import Sequence
from functools import cached_property
from typing import Generic, Literal, Self, TypeVar, override
from tree_sitter import Node as TSNode
from graph_sitter._proxy import proxy_property
from graph_sitter.codebase.codebase_graph import CodebaseGraph
from graph_sitter.codebase.range_index import RangeIndex
from graph_sitter.codebase.span import Range
from graph_sitter.core.assignment import Assignment
from graph_sitter.core.autocommit import commiter, mover, reader, remover, writer
from graph_sitter.core.class_definition import Class
from graph_sitter.core.detached_symbols.code_block import CodeBlock
from graph_sitter.core.directory import Directory
from graph_sitter.core.function import Function
from graph_sitter.core.import_resolution import Import, WildcardImport
from graph_sitter.core.interface import Interface
from graph_sitter.core.interfaces.editable import Editable
from graph_sitter.core.interfaces.has_attribute import HasAttribute
from graph_sitter.core.interfaces.has_block import HasBlock
from graph_sitter.core.interfaces.importable import Importable
from graph_sitter.core.interfaces.usable import Usable
from graph_sitter.core.statements.import_statement import ImportStatement
from graph_sitter.core.symbol import Symbol
from graph_sitter.enums import ImportType, NodeType
from graph_sitter.writer_decorators import apidoc, noapidoc
from graph_visualization.enums import VizNode

logger = ...
class BadWriteError(Exception):
    ...


@apidoc
class File(Editable[None]):
    """Represents a generic file.

    Could represent a source file or a non-code file such as a markdown file or image file.
    """
    name: str
    file_path: str
    node_type: Literal[NodeType.FILE] = ...
    _pending_content_bytes: bytes | None = ...
    _directory: Directory | None
    _pending_imports: set[str]
    _binary: bool = ...
    _range_index: RangeIndex
    def __init__(self, filepath: str, G: CodebaseGraph, ts_node: TSNode | None = ..., binary: bool = ...) -> None:
        ...
    
    @property
    def file(self) -> Self:
        """A property that returns the file object for non-source files.

        This is used by Editable.file to work with non-source files, allowing consistent interface usage across both source and non-source files.

        Returns:
            Self: The current file object.
        """
        ...
    
    @classmethod
    @noapidoc
    def from_content(cls, filepath: str, content: str | bytes, G: CodebaseGraph, sync: bool = ..., binary: bool = ...) -> Self | None:
        """Creates a new file from content."""
        ...
    
    @property
    @noapidoc
    @reader
    def content_bytes(self) -> bytes:
        """Loaded dynamically every time to preserve source of truth.

        TODO: move rest of graph sitter to operate in bytes to prevent multi byte character issues?
        """
        ...
    
    @property
    @reader
    def content(self) -> str:
        """Returns the content of the file as a UTF-8 encoded string.

        Gets the content of the file, either from pending changes or by reading from disk. Binary files cannot be read as strings.

        Args:
            None

        Returns:
            str: The content of the file as a UTF-8 encoded string.

        Raises:
            ValueError: If the file is binary. Use content_bytes instead for binary files.
        """
        ...
    
    @noapidoc
    def write(self, content: str | bytes, to_disk: bool = ...) -> None:
        """Writes string contents to the file."""
        ...
    
    @noapidoc
    def write_bytes(self, content_bytes: bytes, to_disk: bool = ...) -> None:
        ...
    
    @noapidoc
    def write_pending_content(self) -> None:
        ...
    
    @noapidoc
    @writer
    def check_changes(self) -> None:
        ...
    
    @property
    @reader
    def directory(self) -> Directory | None:
        """Returns the directory that contains this file.

        The file can be housed within a directory in the codebase, and this property will return that directory instance.

        Returns:
            Directory | None: The directory containing this file, or None if the file is not in any directory.
        """
        ...
    
    @property
    def is_binary(self) -> bool:
        """Indicates whether the file contains binary data.

        A property that returns True if the file contains binary data, False if it contains text data.

        Returns:
            bool: True if the file contains binary data, False if it contains text data.
        """
        ...
    
    @property
    @reader
    def extension(self) -> str:
        """Returns the file extension.

        Returns:
            str: The file extension including the dot (e.g., '.py', '.ts', '.js').
        """
        ...
    
    @property
    @reader
    def owners(self) -> set[str]:
        """Returns the CODEOWNERS of the file.

        Returns all Github CODEOWNERS associated with this file. If there is no CODEOWNERS file in the codebase, returns an empty set.

        Returns:
            set[str]: A set of Github usernames or team names that own this file. Empty if no CODEOWNERS file exists.
        """
        ...
    
    @cached_property
    @noapidoc
    def github_url(self) -> str | None:
        ...
    
    @property
    @reader
    def start_byte(self) -> int:
        """Returns the starting byte position of a file in its content.

        The start byte is always 0 for a file as it represents the beginning of the file's content.

        Returns:
            int: Always returns 0.
        """
        ...
    
    @remover
    def remove(self) -> None:
        """Removes the file from the file system and graph.

        Queues the file to be removed during the next commit operation. The file will be removed from the filesystem and its node will be removed from the graph.

        Args:
            None

        Returns:
            None
        """
        ...
    
    @property
    def filepath(self) -> str:
        """Retrieves the file path of the file that this Editable instance belongs to.

        Returns:
            str: The file path of the file.
        """
        ...
    
    @mover
    def rename(self, new_name: str) -> None:
        """Renames the file to the specified name, preserving the file extension.

        Args:
            new_name (str): The new name for the file. If the new name includes the file extension, it will be used as-is.
                Otherwise, the original file extension will be preserved.

        Returns:
            None

        Note:
            This method will update all imports that reference this file to use the new filepath.
            The file will be physically moved on disk and all graph references will be updated.
        """
        ...
    
    @mover
    def update_filepath(self, new_filepath: str) -> None:
        """Updates the file path and inbound imports of a file.

        Updates the file path of the file on disk and in the codebase graph. Additionally updates all
        inbound imports to reference the new file path.

        Args:
            new_filepath (str): The new file path to rename the file to.

        Raises:
            BadWriteError: If there are pending file writes that haven't been committed.
            ValueError: If the new file path already exists in the codebase graph.
        """
        ...
    
    def parse(self, G: CodebaseGraph) -> None:
        """Parses the file representation into the graph.

        This method is called during file initialization to parse the file and build its graph representation within the codebase graph.

        Args:
            G (CodebaseGraph): The codebase graph that the file belongs to.

        Returns:
            None
        """
        ...
    


TImport = TypeVar("TImport", bound="Import")
TFunction = TypeVar("TFunction", bound="Function")
TClass = TypeVar("TClass", bound="Class")
TGlobalVar = TypeVar("TGlobalVar", bound="Assignment")
TInterface = TypeVar("TInterface", bound="Interface")
TCodeBlock = TypeVar("TCodeBlock", bound="CodeBlock")
@apidoc
class SourceFile(File, HasBlock, Usable, HasAttribute[Symbol | TImport], Generic[TImport, TFunction, TClass, TGlobalVar, TInterface, TCodeBlock]):
    """Represents a file with source code in the codebase.

    Enables creating, reading, updating, and deleting files and searching through their contents,
    etc.
    """
    code_block: TCodeBlock
    _nodes: list[Importable]
    def __init__(self, ts_node: TSNode, filepath: str, G: CodebaseGraph) -> None:
        ...
    
    @noapidoc
    @commiter
    def parse(self, G: CodebaseGraph) -> None:
        ...
    
    @noapidoc
    @commiter
    def remove_internal_edges(self) -> None:
        """Removes all its direct nodes and edges for each of its internal symbols and imports."""
        ...
    
    @noapidoc
    @commiter
    def unparse(self, reparse: bool = ...) -> list[Importable]:
        """Removes all its direct nodes and edges for each of its internal symbols and imports.

        Returns a list of external import node ids that need to be re-resolved
        """
        ...
    
    @noapidoc
    @commiter
    def sync_with_file_content(self) -> None:
        """Re-parses parent file and re-sets current TSNode."""
        ...
    
    @staticmethod
    @noapidoc
    def get_extensions() -> list[str]:
        """Returns a list of file extensions for the given programming language file."""
        ...
    
    @abstractmethod
    def symbol_can_be_added(self, symbol: Symbol) -> bool:
        """Checks if the file type supports adding the given symbol.

        Determines whether the given symbol can be added to this file based on the symbol's type and the file's
        language/type support.

        Args:
            symbol (Symbol): The symbol to check for add compatibility.

        Returns:
            bool: True if the symbol can be added to this file type, False otherwise.
        """
        ...
    
    @noapidoc
    def invalidate(self): # -> None:
        ...
    
    @classmethod
    @noapidoc
    def from_content(cls, filepath: str, content: str, G: CodebaseGraph, sync: bool = ..., verify_syntax: bool = ...) -> Self | None:
        """Creates a new file from content and adds it to the graph."""
        ...
    
    @classmethod
    @noapidoc
    def create_from_filepath(cls, filepath: str, G: CodebaseGraph) -> Self | None:
        """Makes a new empty file and adds it to the graph.

        Graph-safe.
        """
        ...
    
    @property
    @reader(cache=False)
    def inbound_imports(self) -> list[TImport]:
        """Returns all imports that are importing symbols contained in this file.

        Retrieves a list of Import objects representing imports that reference symbols or content defined in this file.
        This includes imports of symbols declared in the file and imports of the file itself.

        Returns:
            list[TImport]: A list of Import objects that reference content from this file.
        """
        ...
    
    @property
    @reader(cache=False)
    def import_statements(self) -> list[ImportStatement]:
        """Returns all ImportStatements in the file, where each import statement can contain
        multiple imports.

        Retrieves a list of all import statements in the file, sorted by their position. Each ImportStatement can contain
        multiple individual imports (e.g., 'from module import a, b, c').

        Returns:
            list[ImportStatement]: A sorted list of import statements contained in the file.
        """
        ...
    
    @property
    @reader
    def importers(self) -> list[TImport]:
        """Returns all imports that directly imports this file as a module.

        This method returns a list of imports where this file is imported directly as a module,
        not individual symbols from this file.

        For example:
        - `from a import <this file>` will be included
        - `from <this file> import a` will NOT be included

        Args:
            None

        Returns:
            list[TImport]: List of Import objects that import this file as a module,
                sorted by file location.
        """
        ...
    
    @property
    @reader(cache=False)
    def imports(self) -> list[TImport]:
        """List of all Imports in this file.

        Retrieves all imports defined in this file. The imports are sorted by their position in the file.

        Returns:
            list[TImport]: A list of Import instances contained in this file, ordered by their position.
        """
        ...
    
    @reader
    def has_import(self, symbol_alias: str) -> bool:
        """Returns True if the file has an import with the given alias.

        Checks if the file contains an import statement with a specific alias.

        Args:
            symbol_alias (str): The alias to check for in the import statements.

        Returns:
            bool: True if an import with the given alias exists, False otherwise.
        """
        ...
    
    @reader
    def get_import(self, symbol_alias: str) -> TImport | None:
        """Returns the import with matching alias. Returns None if not found.

        Args:
            symbol_alias (str): The alias name to search for. This can match either the direct import name or the aliased name.

        Returns:
            TImport | None: The import statement with the matching alias if found, None otherwise.
        """
        ...
    
    @proxy_property
    def symbols(self, nested: bool = ...) -> list[Symbol | TClass | TFunction | TGlobalVar | TInterface]:
        """Returns all Symbols in the file, sorted by position in the file.

        Args:
            nested: Include nested symbols

        Returns:
            list[Symbol | TClass | TFunction | TGlobalVar | TInterface]: A list of all top-level symbols in the file, sorted by their position in the file. Symbols can be one of the following types:
                - Symbol: Base symbol class
                - TClass: Class definition
                - TFunction: Function definition
                - TGlobalVar: Global variable assignment
                - TInterface: Interface definition
        """
        ...
    
    @reader(cache=False)
    @noapidoc
    def get_nodes(self, *, sort_by_id: bool = ..., sort: bool = ...) -> Sequence[Importable]:
        """Returns all nodes in the file, sorted by position in the file."""
        ...
    
    @reader
    def get_symbol(self, name: str) -> Symbol | None:
        """Gets a symbol by its name from the file.

        Attempts to resolve the symbol by name using name resolution rules first. If that fails,
        searches through the file's symbols list for a direct name match.

        Args:
            name (str): The name of the symbol to find.

        Returns:
            Symbol | None: The found symbol, or None if not found.
        """
        ...
    
    @property
    @reader(cache=False)
    def symbols_sorted_topologically(self) -> list[Symbol]:
        """Returns all Symbols in the file, sorted topologically (parents first). Robust to
        dependency loops.

        Performs a topological sort of the symbols in the file based on symbol dependencies. This ensures that parent symbols
        appear before their dependents while handling potential dependency loops gracefully.

        Args:
            None

        Returns:
            list[Symbol]: A list of symbols sorted topologically with parents appearing before their dependents.
        """
        ...
    
    @property
    @reader(cache=False)
    def global_vars(self) -> list[TGlobalVar]:
        """Returns all GlobalVars in the file.

        Retrieves all global variables (assignments) defined at the top level in the file, sorted by their position in the file.

        Returns:
            list[TGlobalVar]: A list of global variable assignments, where each element is an Assignment representing a global variable.
        """
        ...
    
    @reader
    def get_global_var(self, name: str) -> TGlobalVar | None:
        """Returns a specific global var by name. Returns None if not found.

        Args:
            name (str): The name of the global variable to find.

        Returns:
            TGlobalVar | None: The global variable if found, None otherwise.
        """
        ...
    
    @property
    @reader(cache=False)
    def classes(self) -> list[TClass]:
        """Returns all Classes in the file.

        Returns a list of all Classes defined in the file, sorted by position in the file.
        Use this method to iterate over all classes in a file or to get information about class definitions.

        Returns:
            list[TClass]: A list of Class objects in the file, sorted by position in the file.
        """
        ...
    
    @reader
    def get_class(self, name: str) -> TClass | None:
        """Returns a specific Class by full name. Returns None if not found.

        Searches for a class in the file with the specified name. Similar to get_symbol, but specifically for Class types.

        Args:
            name (str): The full name of the class to search for.

        Returns:
            TClass | None: The matching Class object if found, None otherwise.
        """
        ...
    
    @property
    @reader(cache=False)
    def functions(self) -> list[TFunction]:
        """Returns all Functions in the file.

        Returns a list of all top-level functions defined in the file, sorted by their position in the file.
        Does not include nested functions (functions defined within other functions or classes).

        Returns:
            list[TFunction]: A list of Function objects representing all top-level functions in the file.
        """
        ...
    
    @reader
    def get_function(self, name: str) -> TFunction | None:
        """Returns a specific Function by name.

        Gets a Function object from the file by searching for a function with the given name.

        Args:
            name (str): The name of the function to find.

        Returns:
            TFunction | None: The matching Function object if found, None otherwise.
        """
        ...
    
    @noapidoc
    @reader
    def get_node_by_name(self, name: str) -> Symbol | TImport | None:
        """Returns something defined in this file by name.

        Used during import resolution
        """
        ...
    
    @cached_property
    @noapidoc
    @reader(cache=True)
    def valid_symbol_names(self) -> dict[str, Symbol | TImport | WildcardImport[TImport]]:
        """Returns a dict mapping name => Symbol (or import) in this file."""
        ...
    
    @noapidoc
    @reader
    def resolve_name(self, name: str, start_byte: int | None = ...) -> Symbol | Import | WildcardImport | None:
        ...
    
    @property
    @reader
    def import_module_name(self) -> str:
        """Returns the module name that this file gets imported as.

        Gets the module name for this file in the context of imports. This name is used when other files import this file, either directly or when importing symbols from this file.

        Returns:
            str: The module name used when importing this file.
        """
        ...
    
    @classmethod
    @abstractmethod
    @noapidoc
    def get_import_module_name_for_file(cls, filepath: str, G: CodebaseGraph) -> str:
        ...
    
    @abstractmethod
    def remove_unused_exports(self): # -> None:
        """Removes unused exports from the file.

        Removes all exports that have no usages by any other files in the codebase. This helps reduce unnecessary exports and maintain a cleaner API surface.

        Returns:
            None
        """
        ...
    
    @mover
    def update_filepath(self, new_filepath: str) -> None:
        """Renames the file and updates all imports to point to the new location.

        When a file is renamed, this method does three things:
        1. Creates a new file node in the graph with the new filepath
        2. Moves the file on disk to the new location
        3. Updates all inbound imports to point to the new module location

        Args:
            new_filepath (str): The new filepath to move the file to.

        Returns:
            None
        """
        ...
    
    @writer
    def add_symbol_import(self, symbol: Symbol, alias: str | None = ..., import_type: ImportType = ..., is_type_import: bool = ...): # -> TImport | None:
        """Adds an import to a file for a given symbol.

        This method adds an import statement to the file for a specified symbol. If an import for the
        symbol already exists, it returns the existing import instead of creating a new one.

        Args:
            symbol (Symbol): The symbol to import.
            alias (str | None): Optional alias for the imported symbol. Defaults to None.
            import_type (ImportType): The type of import to use. Defaults to ImportType.UNKNOWN.
            is_type_import (bool): Whether this is a type-only import. Defaults to False.

        Returns:
            Import: The created or existing import for the symbol.
        """
        ...
    
    @writer(commit=False)
    def add_import_from_import_string(self, import_string: str) -> None:
        """Adds import to the file from a string representation of an import statement.

        This method adds a new import statement to the file based on its string representation.
        If the import already exists in the file, or is pending to be added, it won't be added again.
        If there are existing imports, the new import will be added before the first import,
        otherwise it will be added at the beginning of the file.

        Args:
            import_string (str): The string representation of the import statement to add.

        Returns:
            None
        """
        ...
    
    @writer
    def add_symbol_from_source(self, source: str) -> None:
        """Adds a symbol to a file from a string representation.

        This method adds a new symbol definition to the file by appending its source code string. The symbol will be added
        after existing symbols if present, otherwise at the beginning of the file.

        Args:
            source (str): String representation of the symbol to be added. This should be valid source code for
                the file's programming language.

        Returns:
            None: The symbol is added directly to the file's content.
        """
        ...
    
    @writer
    def add_symbol(self, symbol: Symbol, should_export: bool = ...): # -> Symbol[Any, Any] | None:
        """Adds `symbol` to the file.

        Adds the given symbol to the file, optionally exporting it if applicable. If the symbol already exists in the file, returns the existing symbol.

        Args:
            symbol (Symbol): The symbol to add to the file.
            should_export (bool, optional): Whether to export the symbol. Defaults to True.

        Returns:
            Symbol: The added symbol, or the existing symbol if it already exists in the file.

        Raises:
            ValueError: If the symbol type cannot be added to this file type.
        """
        ...
    
    @noapidoc
    @writer
    def convert_js_to_esm(self) -> None:
        """Converts a JS file to an ES module."""
        ...
    
    @property
    @noapidoc
    def viz(self) -> VizNode:
        ...
    
    @property
    @noapidoc
    @reader(cache=True)
    def valid_import_names(self) -> dict[str, Symbol | TImport | WildcardImport[TImport]]:
        """Returns a dict mapping name => Symbol (or import) in this file that can be imported from
        another file.
        """
        ...
    
    @noapidoc
    @reader
    @override
    def resolve_attribute(self, name: str) -> Symbol | TImport | None:
        ...
    
    @property
    @noapidoc
    def self_dest(self) -> HasBlock:
        """Returns the symbol usage resolution destination node for the symbol."""
        ...
    
    @property
    @noapidoc
    def parent_symbol(self) -> Self:
        ...
    
    @reader
    def find_by_byte_range(self, range: Range) -> list[Editable]:
        """Finds all editable objects that overlap with the given byte range in the file.

        Uses the file's range index to efficiently retrieve all editable objects (like functions,
        classes, variables) that intersect with the specified byte range.

        Args:
            range (Range): The byte range to search within the file.

        Returns:
            list[Editable]: A list of all Editable objects that overlap with the given range.
        """
        ...
    
    @property
    @noapidoc
    def descendant_symbols(self) -> list[Importable]:
        ...
    


