resolve method

Future<ProgramElement> resolve()

Implementation

Future<ProgramElement> resolve() async {
  const core = DartSdkPackage(name: 'core');
  final programElement = ProgramElement();
  final syntheticTypeDefinitions = await _resolvePackage(core);

  final importsDeclarations = <ImportDeclaration>[];
  final importsElementsFuture = <Future<ImportElement>>[];

  // At this point, imports should be guaranteed to come before anything else.
  // This is guaranteed in the parser (maybe not the best place?).

  for (final importDeclaration in program.whereType<ImportDeclaration>()) {
    try {
      importsDeclarations.add(importDeclaration);
      importsElementsFuture.add(
        () async {
          final import = await importDeclaration.accept(this) as ImportElement;
          import.enclosingElement = programElement;
          programElement.imports.add(import);
          return import;
        }(),
      );
    } on ResolveError catch (error) {
      _errorHandler?.emit(error);
    }
  }

  final importElements = await importsElementsFuture.wait;
  for (int i = 0; i < importElements.length; i++) {
    try {
      try {
        final element = importElements[i];

        syntheticTypeDefinitions.addAll(
          await _resolvePackage(element.package),
        );

        for (final definition in syntheticTypeDefinitions) {
          programElement.declarations.add(definition);
          definition.enclosingElement = programElement;
        }
      } on Exception {
        final declaration = importsDeclarations[i];
        throw ImportedPackageNotAvailableError(declaration.identifier);
      }
    } on ResolveError catch (error) {
      _errorHandler?.emit(error);
    }
  }

  for (final declaration in program.whereNot((declaration) => declaration is ImportDeclaration)) {
    try {
      if (declaration is LetDeclaration) {
        final letVariableDeclaration = await declaration.accept(this) as DeclarationElement;
        letVariableDeclaration.enclosingElement = programElement;
        programElement.declarations.add(letVariableDeclaration);
      } else {
        final typeDefinition = await declaration.accept(this) as TypeDefinitionElement;
        typeDefinition.enclosingElement = programElement;
        programElement.declarations.add(typeDefinition);
      }
    } on ResolveError catch (error) {
      _errorHandler?.emit(error);
    }
  }

  for (final MapEntry(key: parameterElement, value: node) in _unresolvedParameters.entries) {
    try {
      parameterElement.type = _resolveTypeIdentifier(node.typeIdentifier);
    } on _SymbolNotResolved {
      // TODO(mateusfccp): do better
      final type = node.typeIdentifier as IdentifiedTypeIdentifier;
      _errorHandler?.emit(
        SymbolNotInScopeError(type.identifier),
      );
    }
  }

  return programElement;
}