docs: @Override
      public void build(IClassPath classPath, IClassPathBuilderProgress progress) throws CheckedAnalysisException, IOException,
      InterruptedException {
          // Discover all directly and indirectly referenced codebases
          processWorkList(classPath, projectWorkList, progress);
  
          // If not already located, try to locate any additional codebases
          // containing classes required for analysis.
          if (!discoveredCodeBaseList.isEmpty()) {
              locateCodebasesRequiredForAnalysis(classPath, progress);
          }
  
          // Add all discovered codebases to the classpath
          for (DiscoveredCodeBase discoveredCodeBase : discoveredCodeBaseList) {
              classPath.addCodeBase(discoveredCodeBase.getCodeBase());
          }
  
          Set<ClassDescriptor> appClassSet = new HashSet<>();
  
          // Build collection of all application classes.
          // Also, add resource name -> codebase entry mappings for application
          // classes.
          for (DiscoveredCodeBase discoveredCodeBase : discoveredCodeBaseList) {
              if (!discoveredCodeBase.getCodeBase().isApplicationCodeBase()) {
                  continue;
              }
  
              codeBaseEntryLoop: for (ICodeBaseIterator i = discoveredCodeBase.iterator(); i.hasNext();) {
                  ICodeBaseEntry entry = i.next();
                  if (!DescriptorFactory.isClassResource(entry.getResourceName())) {
                      continue;
                  }
  
                  ClassDescriptor classDescriptor = entry.getClassDescriptor();
                  if (classDescriptor == null) {
                      throw new IllegalStateException();
                  }
  
                  if (appClassSet.contains(classDescriptor)) {
                      // An earlier entry takes precedence over this class
                      continue codeBaseEntryLoop;
                  }
                  appClassSet.add(classDescriptor);
                  appClassList.add(classDescriptor);
  
                  classPath.mapResourceNameToCodeBaseEntry(entry.getResourceName(), entry);
              }
          }
  
          if (DEBUG) {
              System.out.println("Classpath:");
              dumpCodeBaseList(classPath.appCodeBaseIterator(), "Application codebases");
              dumpCodeBaseList(classPath.auxCodeBaseIterator(), "Auxiliary codebases");
          }
  
          // Make sure we always know if we can't find system classes
          ICodeBaseEntry resource = classPath.lookupResource("java/lang/Object.class");
          if(resource == null){
              throw new ResourceNotFoundException("java/lang/Object.class");
          }
      }