/**
  * Search the top-level functions defined in the given compilation unit for the entry point.
  *
  * @param element the compilation unit to be searched
  * @return the entry point that was found, or {@code null} if the compilation unit does not define
  *     an entry point
  */
 private FunctionElement findEntryPoint(CompilationUnitElementImpl element) {
   for (FunctionElement function : element.getFunctions()) {
     if (function.getName().equals(ENTRY_POINT_NAME)) {
       return function;
     }
   }
   return null;
 }
  /**
   * Build the library element for the given library.
   *
   * @param library the library for which an element model is to be built
   * @return the library element that was built
   * @throws AnalysisException if the analysis could not be performed
   */
  public LibraryElementImpl buildLibrary(Library library) throws AnalysisException {
    CompilationUnitBuilder builder = new CompilationUnitBuilder();
    Source librarySource = library.getLibrarySource();
    CompilationUnit definingCompilationUnit = library.getDefiningCompilationUnit();
    CompilationUnitElementImpl definingCompilationUnitElement =
        builder.buildCompilationUnit(librarySource, definingCompilationUnit);
    NodeList<Directive> directives = definingCompilationUnit.getDirectives();
    LibraryIdentifier libraryNameNode = null;
    boolean hasPartDirective = false;
    FunctionElement entryPoint = findEntryPoint(definingCompilationUnitElement);
    ArrayList<Directive> directivesToResolve = new ArrayList<Directive>();
    ArrayList<CompilationUnitElementImpl> sourcedCompilationUnits =
        new ArrayList<CompilationUnitElementImpl>();
    for (Directive directive : directives) {
      //
      // We do not build the elements representing the import and export directives at this point.
      // That is not done until we get to LibraryResolver.buildDirectiveModels() because we need the
      // LibraryElements for the referenced libraries, which might not exist at this point (due to
      // the possibility of circular references).
      //
      if (directive instanceof LibraryDirective) {
        if (libraryNameNode == null) {
          libraryNameNode = ((LibraryDirective) directive).getName();
          directivesToResolve.add(directive);
        }
      } else if (directive instanceof PartDirective) {
        PartDirective partDirective = (PartDirective) directive;
        StringLiteral partUri = partDirective.getUri();
        Source partSource = partDirective.getSource();
        if (analysisContext.exists(partSource)) {
          hasPartDirective = true;
          CompilationUnit partUnit = library.getAST(partSource);
          CompilationUnitElementImpl part = builder.buildCompilationUnit(partSource, partUnit);
          part.setUriOffset(partUri.getOffset());
          part.setUriEnd(partUri.getEnd());
          part.setUri(partDirective.getUriContent());
          //
          // Validate that the part contains a part-of directive with the same name as the library.
          //
          String partLibraryName = getPartLibraryName(partSource, partUnit, directivesToResolve);
          if (partLibraryName == null) {
            errorListener.onError(
                new AnalysisError(
                    librarySource,
                    partUri.getOffset(),
                    partUri.getLength(),
                    CompileTimeErrorCode.PART_OF_NON_PART,
                    partUri.toSource()));
          } else if (libraryNameNode == null) {
            // TODO(brianwilkerson) Collect the names declared by the part. If they are all the same
            // then we can use that name as the inferred name of the library and present it in a
            // quick-fix.
            // partLibraryNames.add(partLibraryName);
          } else if (!libraryNameNode.getName().equals(partLibraryName)) {
            errorListener.onError(
                new AnalysisError(
                    librarySource,
                    partUri.getOffset(),
                    partUri.getLength(),
                    StaticWarningCode.PART_OF_DIFFERENT_LIBRARY,
                    libraryNameNode.getName(),
                    partLibraryName));
          }
          if (entryPoint == null) {
            entryPoint = findEntryPoint(part);
          }
          directive.setElement(part);
          sourcedCompilationUnits.add(part);
        }
      }
    }

    if (hasPartDirective && libraryNameNode == null) {
      errorListener.onError(
          new AnalysisError(librarySource, ResolverErrorCode.MISSING_LIBRARY_DIRECTIVE_WITH_PART));
    }
    //
    // Create and populate the library element.
    //
    LibraryElementImpl libraryElement =
        new LibraryElementImpl(analysisContext.getContextFor(librarySource), libraryNameNode);
    libraryElement.setDefiningCompilationUnit(definingCompilationUnitElement);
    if (entryPoint != null) {
      libraryElement.setEntryPoint(entryPoint);
    }
    int sourcedUnitCount = sourcedCompilationUnits.size();
    libraryElement.setParts(
        sourcedCompilationUnits.toArray(new CompilationUnitElementImpl[sourcedUnitCount]));
    for (Directive directive : directivesToResolve) {
      directive.setElement(libraryElement);
    }
    library.setLibraryElement(libraryElement);
    if (sourcedUnitCount > 0) {
      patchTopLevelAccessors(libraryElement);
    }
    return libraryElement;
  }