/** * DomainLang Scope Provider * * Implements import-based scoping with alias support and package-boundary transitive imports. * * **Key Concepts (per ADR-003):** * - Elements are only visible if defined in current document OR explicitly imported * - Import aliases control visibility: `import "pkg" as ddd` makes types visible as `ddd.*` only * - Package-boundary transitive imports: External packages (.dlang/packages/) can re-export * - Local file imports remain non-transitive (explicit dependencies only) * * **Why this matters:** * Without this, Langium's DefaultScopeProvider would make ALL indexed documents visible * in the global scope, which would: * 1. Allow referencing elements that haven't been imported * 2. Make the import system meaningless * 3. Create confusion about dependencies between files * * @see https://langium.org/docs/recipes/scoping/ for Langium scoping patterns * @see ADR-003 for alias and package-boundary design decisions */ import type { ReferenceInfo, Scope } from 'langium'; import { DefaultScopeProvider } from 'langium'; import type { DomainLangServices } from '../domain-lang-module.js'; /** * Custom scope provider that restricts cross-file references to imported documents only. * * Extends Langium's DefaultScopeProvider to override the global scope computation. */ export declare class DomainLangScopeProvider extends DefaultScopeProvider { /** * Reference to IndexManager for getting resolved imports with aliases. */ private readonly domainLangIndexManager; /** * Detects package boundaries for transitive import resolution. */ private readonly packageBoundaryDetector; /** * Caches the element description index by reference type. * Invalidated automatically when any document in the workspace changes. */ private readonly descByUriCache; constructor(services: DomainLangServices); /** * Override getGlobalScope to implement alias-scoped and package-boundary transitive imports. * * The default Langium behavior includes ALL documents in the workspace. * We restrict and transform scope to: * 1. The current document's own exported symbols * 2. Symbols from directly imported documents (with alias prefixing) * 3. Symbols from package-boundary transitive imports (external packages only) * * @param referenceType - The AST type being referenced * @param context - Information about the reference * @returns A scope containing only visible elements */ protected getGlobalScope(referenceType: string, context: ReferenceInfo): Scope; /** * Computes all visible descriptions for a document, including: * - Current document's own symbols * - Direct imports (with alias prefixing) * - Package-boundary transitive imports * * @param referenceType - The AST type being referenced * @param document - The document making the reference * @returns Stream of visible descriptions */ private computeVisibleDescriptions; /** * Adds descriptions from a single import using the pre-computed descByUri index. */ private addDescriptionsFromImportFast; /** * Adds package-boundary transitive imports for external packages. * * When document A imports package document B (e.g., index.dlang), * and B imports internal package files C, D, etc. (same package root), * then A can see types from C, D, etc. (package re-exports). * * Local file imports remain non-transitive. * * @param imp - Import information for the direct import * @param descByUri - Pre-computed index of descriptions by document URI * @param currentDocument - The document making the reference * @param processedUris - Set of already-processed URIs to avoid duplicates * @param output - Array to append visible descriptions to */ private addPackageBoundaryTransitiveImports; /** * Creates an alias-prefixed version of a description. * * Example: CoreDomain with alias "ddd" → ddd.CoreDomain * * @param original - Original description * @param alias - Import alias to prefix with * @returns New description with prefixed name */ private createAliasedDescription; }