classes/ScopeManager.ps1

class ScopeManager {
    [int]$nextScopeId = 0
    [System.Collections.Generic.Stack[int]]$scopeStack
    [System.Collections.Generic.List[object]]$scopes


    ScopeManager() {
        $this.scopeStack = [System.Collections.Generic.Stack[int]]::new()
        $this.scopes = [System.Collections.Generic.List[Scope]]::new()
        $this.EnterNewScope(0,1,1)
    }


    [void] EnterNewScope([string]$name, [int]$startIndex, [int]$line, [int]$column) {
        $scope = [Scope]::new()
        $scope.id = $this.nextScopeId++
        $scope.Name = $name
        $scope.parentId = if ($this.scopeStack.Count -gt 0) { $this.scopeStack.Peek() } else { 0 }
        $scope.startIndex = $startIndex
        $scope.StartLine = $line
        $scope.StartColumn = $column
        $this.scopes.Add($scope)
        $this.scopeStack.Push($scope.Id)
    }


    [void] EnterNewScope([int]$startIndex, [int]$line, [int]$column) {
        $this.EnterNewScope("", $startIndex, $line, $column)
    }


    [void] ExitNewScope([int]$endIndex, [int]$line, [int]$column) {
        $id = $this.scopeStack.Pop()
        $scope = $this.scopes | Where-Object { $_.id -eq $id }
        $scope.endIndex = $endIndex
        $scope.EndLine = $line
        $scope.EndColumn = $column
        if ($this.scopeStack.Count -eq 0) {
            $this.EnterScope(0)
        }
    }


    [void] EnterScope([int]$startIndex) {
        $scope = $this.scopes | Where-Object { $_.startIndex -eq $startIndex }
        $this.scopeStack.Push($scope.Id)
    }


    [void] ExitScope() {
        $null = $this.scopeStack.Pop()
    }


    [int] GetCurrentScope() {
        return $this.scopeStack.Peek()
    }


    [Scope] GetScopeById([int] $id) {
        return $this.Scopes | Where-Object { $_.Id -eq $id }
    }


    [Scope] GetScopeByIndex([int] $index) {
        return $this.Scopes | Where-Object { $_.StartIndex -le $index -and $_.EndIndex -ge $index } | Sort-Object StartIndex -Descending | Select-Object -First 1
    }


    [bool] IsVisible([int] $definitionScopeId, [int] $currentScopeId) {
        if ($definitionScopeId -eq $currentScopeId) {
            return $true
        }

        $current = $this.GetScopeById($currentScopeId)
        while ($current -and $current.ParentId -ne 0) {
            if ($current.ParentId -eq $definitionScopeId) {
                return $true
            }
            $current = $this.GetScopeById($current.ParentId)
        }

        return $false
    }

}