Class ServerContextProvider

java.lang.Object
com.github._1c_syntax.bsl.languageserver.context.ServerContextProvider

@Component public class ServerContextProvider extends Object
Провайдер контекстов сервера для мульти-workspace окружения.

Управляет коллекцией экземпляров ServerContext (по одному на каждую workspace folder) и обеспечивает маршрутизацию от URI документа к контексту сервера.

  • Field Details

    • DEFAULT_WORKSPACE_URI

      public static final URI DEFAULT_WORKSPACE_URI
      Синтетический URI дефолтного («безворкспейсного») контекста. Создаётся, когда клиент при инициализации не прислал ни одной workspace folder, ни rootUri/rootPath (режим открытия одиночного файла или untitled-буфера). Схема не file — этот URI не должен попадать в код, приводящий URI к файловому пути (Absolute.path, Path.of).
  • Constructor Details

  • Method Details

    • addWorkspace

      public ServerContext addWorkspace(WorkspaceFolder workspaceFolder)
      Добавить workspace folder и создать для нее контекст сервера.
      Parameters:
      workspaceFolder - информация о workspace folder
      Returns:
      созданный контекст сервера
    • addWorkspace

      public ServerContext addWorkspace(URI workspaceUri)
      Добавить workspace по URI и создать для нее контекст сервера.
      Parameters:
      workspaceUri - нормализованный через Absolute.uri(URI) URI корня workspace
      Returns:
      созданный контекст сервера
    • addWorkspace

      public ServerContext addWorkspace(URI workspaceUri, @Nullable String workspaceName)
      Добавить workspace по URI и создать для нее контекст сервера.

      workspaceUri должен быть нормализован через Absolute.uri(URI) — иначе clear() / removeWorkspace(WorkspaceFolder) не смогут найти запись по ключу (они ищут через Absolute.uri(...) ещё раз).

      Parameters:
      workspaceUri - нормализованный URI корня workspace
      workspaceName - имя workspace (если null — извлекается из URI)
      Returns:
      созданный контекст сервера
    • registerDefaultWorkspace

      public ServerContext registerDefaultWorkspace()
      Создать дефолтный («безворкспейсный») контекст сервера.

      Используется, когда при инициализации не переданы ни workspace folders, ни rootUri/rootPath (открыт одиночный файл или untitled-буфер). Контекст создаётся с configurationRoot == null, поэтому ServerContext.populateContext() ничего не сканирует. Документы, не попавшие ни в один workspace, маршрутизируются в него (или в первый добавленный workspace) — см. resolveContextForDocument(URI).

      В отличие от addWorkspace(URI, String), метод намеренно не публикует WorkspaceAddedEvent: синтетический URI не является файловым, и подписчики, приводящие URI к пути (наблюдатели файлов конфигурации/библиотек), на нём падали бы.

      Returns:
      дефолтный контекст сервера (идемпотентно: повторные вызовы возвращают существующий)
    • removeWorkspace

      public void removeWorkspace(WorkspaceFolder workspaceFolder)
      Удалить workspace folder и очистить ее контекст сервера.
      Parameters:
      workspaceFolder - информация о workspace folder
    • getServerContextUnsafe

      public Optional<ServerContext> getServerContextUnsafe(URI documentUri)
      Получить контекст сервера для URI документа (с нормализацией URI).

      Используется для внешних вызовов, где URI может быть не нормализован.

      Parameters:
      documentUri - URI документа (будет нормализован)
      Returns:
      контекст сервера, содержащий документ, или пустой Optional, если не найден
    • getServerContext

      public Optional<ServerContext> getServerContext(URI documentUri)
      Получить контекст сервера для URI документа.

      Сначала ищет в индексе документов (O(1)), затем по URI workspace (для новых документов). URI должен быть уже нормализован через Absolute.uri(URI). Используется Absolute.uri(URI) для канонизации, что работает со всеми схемами URI.

      Parameters:
      documentUri - нормализованный URI документа
      Returns:
      контекст сервера, содержащий документ, или пустой Optional, если не найден
    • resolveContextForDocument

      public ServerContext resolveContextForDocument(URI documentUri)
      Определить контекст сервера для документа с фолбэком на главный workspace.

      Сначала ищет владеющий контекст по правилам getServerContext(URI) (индекс, затем префикс URI workspace). Если документ не относится ни к одному корню (untitled-буфер, файл вне папок проекта, одиночный файл), маршрутизирует его в главный контекст (getPrimaryContext()). URI нормализуется через Absolute.uri(URI).

      Parameters:
      documentUri - URI документа (будет нормализован)
      Returns:
      контекст сервера для документа (никогда не null)
      Throws:
      IllegalStateException - если не зарегистрирован ни один контекст (провайдер используется до initialize() или после shutdown())
    • getDocumentUnsafe

      public Optional<DocumentContext> getDocumentUnsafe(String uri)
      Получить документ по строковому URI с нормализацией.

      Ищет документ во всех зарегистрированных контекстах. Используется для внешних вызовов, где URI может быть не нормализован.

      Parameters:
      uri - строковый URI документа
      Returns:
      Контекст документа, если найден
    • getDocumentUnsafe

      public Optional<DocumentContext> getDocumentUnsafe(URI uri)
      Получить документ по URI с нормализацией.

      Ищет документ во всех зарегистрированных контекстах. Используется для внешних вызовов, где URI может быть не нормализован.

      Parameters:
      uri - URI документа (будет нормализован)
      Returns:
      Контекст документа, если найден
    • getDocument

      public Optional<DocumentContext> getDocument(URI uri)
      Получить документ по нормализованному URI.

      URI должен быть уже нормализован через Absolute.uri(URI).

      Parameters:
      uri - нормализованный URI документа
      Returns:
      Контекст документа, если найден
    • getDocumentNoLock

      public Optional<DocumentContext> getDocumentNoLock(URI uri)
      Получить документ по URI без захвата per-document RWLock.

      Используется горячими путями инференции (reference finders, type inferencer), которые массово опрашивают документы во время populateContext. RWLock с queued writer'ом блокирует новых readers (fair-mode), что приводит к парку всех worker-потоков.

      Безопасно для read-only-доступа: документы не пересоздаются, они обновляются in-place под write-lock'ом; чтение без лока даёт snapshot текущего AST/symbol-tree, что допустимо для type-инференции (та и без того eventually-consistent относительно правок пользователя).

    • getDocumentUnsafeNoLock

      public Optional<DocumentContext> getDocumentUnsafeNoLock(URI uri)
      То же, что getDocumentNoLock(URI), но с нормализацией. Аналог getDocumentUnsafe(URI) для контекстов, где нельзя брать per-document RWLock (см. документацию к getDocumentNoLock(URI)).
    • getAllContexts

      public Map<URI, ServerContext> getAllContexts()
      Получить все контексты серверов с их URI.
      Returns:
      неизменяемая карта URI → контекст сервера
    • clear

      public void clear()
      Очистить все workspaces.
    • onDocumentAdded

      @EventListener public void onDocumentAdded(ServerContextDocumentAddedEvent event)
      Обработчик события добавления документа в контекст. Добавляет документ в индекс для быстрого поиска.
    • onDocumentRemoved

      @EventListener public void onDocumentRemoved(ServerContextDocumentRemovedEvent event)
      Обработчик события удаления документа из контекста. Удаляет документ из индекса.