import { StreamScope as a, MapScope as l } from "./scope.js";
import { getDocument as h } from "../utils/ast-utils.js";
import { stream as c } from "../utils/stream.js";
import { WorkspaceCache as d } from "../utils/caching.js";
class w {
  constructor(e) {
    this.reflection = e.shared.AstReflection, this.nameProvider = e.references.NameProvider, this.descriptions = e.workspace.AstNodeDescriptionProvider, this.indexManager = e.shared.workspace.IndexManager, this.globalScopeCache = new d(e.shared);
  }
  getScope(e) {
    const r = [], o = this.reflection.getReferenceType(e), i = h(e.container).precomputedScopes;
    if (i) {
      let t = e.container;
      do {
        const s = i.get(t);
        s.length > 0 && r.push(c(s).filter((p) => this.reflection.isSubtype(p.type, o))), t = t.$container;
      } while (t);
    }
    let n = this.getGlobalScope(o, e);
    for (let t = r.length - 1; t >= 0; t--)
      n = this.createScope(r[t], n);
    return n;
  }
  /**
   * Create a scope for the given collection of AST node descriptions.
   */
  createScope(e, r, o) {
    return new a(c(e), r, o);
  }
  /**
   * Create a scope for the given collection of AST nodes, which need to be transformed into respective
   * descriptions first. This is done using the `NameProvider` and `AstNodeDescriptionProvider` services.
   */
  createScopeForNodes(e, r, o) {
    const i = c(e).map((n) => {
      const t = this.nameProvider.getName(n);
      if (t)
        return this.descriptions.createDescription(n, t);
    }).nonNullable();
    return new a(i, r, o);
  }
  /**
   * Create a global scope filtered for the given reference type.
   */
  getGlobalScope(e, r) {
    return this.globalScopeCache.get(e, () => new l(this.indexManager.allElements(e)));
  }
}
export {
  w as DefaultScopeProvider
};
