public ModuleChunkClasspath()

in generate-ant/src/main/java/com/intellij/compiler/ant/ModuleChunkClasspath.java [36:175]


  public ModuleChunkClasspath(final ModuleChunk chunk,
                              final GenerationOptions genOptions,
                              final boolean generateRuntimeClasspath,
                              final boolean generateTestClasspath) {
    super(generateClasspathName(chunk, generateRuntimeClasspath, generateTestClasspath));

    final OrderedSet<ClasspathItem> pathItems =
      new OrderedSet<>();
    final String moduleChunkBasedirProperty = BuildProperties.getModuleChunkBasedirProperty(chunk);
    final Module[] modules = chunk.getModules();
    // processed chunks (used only in runtime classpath), every chunk is referenced exactly once
    final Set<ModuleChunk> processedChunks = new HashSet<>();
    // pocessed modules
    final Set<Module> processedModules = new HashSet<>();
    for (final Module module : modules) {
      new Object() {
        /**
         * Process the module. The logic is different for compile-time case and runtime case.
         * In the case of runtime, only directly referenced objects are included in classpath.
         * Indirectly referenced are
         *
         * @param module a module to process.
         * @param dependencyLevel is increased with every of recursion.
         * @param isModuleExported if true the module is exported from the previous level
         */
        public void processModule(final Module module, final int dependencyLevel, final boolean isModuleExported) {
          if (processedModules.contains(module)) {
            // the module is already processed, nothing should be done
            return;
          }
          if (dependencyLevel > 1 && !isModuleExported && !(genOptions.inlineRuntimeClasspath && generateRuntimeClasspath)) {
            // the module is not in exports and it is not directly included skip it in the case of library pathgeneration
            return;
          }
          processedModules.add(module);
          final ProjectEx project = (ProjectEx)chunk.getProject();
          final File baseDir = BuildProperties.getProjectBaseDir(project);
          OrderEnumerator enumerator = ModuleRootManager.getInstance(module).orderEntries();
          if (generateRuntimeClasspath) {
            enumerator = enumerator.runtimeOnly();
          }
          else {
            enumerator = enumerator.compileOnly();
            if (!generateTestClasspath && (dependencyLevel == 0 || chunk.contains(module))) {
              // this is the entry for outpath of the currently processed module
              // the root module is never included
              enumerator = enumerator.withoutModuleSourceEntries();
            }
          }
          if (!generateTestClasspath) {
            enumerator = enumerator.productionOnly();
          }
          enumerator.forEach(orderEntry -> {
            if (!orderEntry.isValid()) {
              return true;
            }

            if (!generateRuntimeClasspath &&
                !(orderEntry instanceof ModuleOrderEntry) &&
                !(orderEntry instanceof ModuleSourceOrderEntry)) {
              // needed for compilation classpath only
              final boolean isExported = (orderEntry instanceof ExportableOrderEntry) && ((ExportableOrderEntry)orderEntry).isExported();
              if (dependencyLevel > 0 && !isExported) {
                // non-exported dependencies are excluded and not processed
                return true;
              }
            }

            if (orderEntry instanceof JdkOrderEntry) {
              if (genOptions.forceTargetJdk && !generateRuntimeClasspath) {
                pathItems
                  .add(new PathRefItem(BuildProperties.propertyRef(BuildProperties.getModuleChunkJdkClasspathProperty(chunk.getName()))));
              }
            }
            else if (orderEntry instanceof ModuleOrderEntry) {
              final ModuleOrderEntry moduleOrderEntry = (ModuleOrderEntry)orderEntry;
              final Module dependentModule = moduleOrderEntry.getModule();
              if (!chunk.contains(dependentModule)) {
                if (generateRuntimeClasspath && !genOptions.inlineRuntimeClasspath) {
                  // in case of runtime classpath, just an referenced to corresponding classpath is created
                  final ModuleChunk depChunk = genOptions.getChunkByModule(dependentModule);
                  if (!processedChunks.contains(depChunk)) {
                    // chunk references are included in the runtime classpath only once
                    processedChunks.add(depChunk);
                    String property = generateTestClasspath ? BuildProperties.getTestRuntimeClasspathProperty(depChunk.getName())
                                                            : BuildProperties.getRuntimeClasspathProperty(depChunk.getName());
                    pathItems.add(new PathRefItem(property));
                  }
                }
                else {
                  // in case of compile classpath or inlined runtime classpath,
                  // the referenced module is processed recursively
                  processModule(dependentModule, dependencyLevel + 1, moduleOrderEntry.isExported());
                }
              }
            }
            else if (orderEntry instanceof LibraryOrderEntry) {
              final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)orderEntry;
              final String libraryName = libraryOrderEntry.getLibraryName();
              if (((LibraryOrderEntry)orderEntry).isModuleLevel()) {
                CompositeGenerator gen = new CompositeGenerator();
                gen.setHasLeadingNewline(false);
                LibraryDefinitionsGeneratorFactory.genLibraryContent(project, genOptions, libraryOrderEntry.getLibrary(), baseDir, gen);
                pathItems.add(new GeneratorItem(libraryName, gen));
              }
              else {
                pathItems.add(new PathRefItem(BuildProperties.getLibraryPathId(libraryName)));
              }
            }
            else if (orderEntry instanceof ModuleSourceOrderEntry) {
              // Module source entry?
              for (String url : getCompilationClasses(module, ((GenerationOptionsImpl)genOptions), generateRuntimeClasspath,
                                                      generateTestClasspath, dependencyLevel == 0)) {
                url = StringUtil.trimEnd(url, JarFileSystem.JAR_SEPARATOR);
                final String propertyRef = genOptions.getPropertyRefForUrl(url);
                if (propertyRef != null) {
                  pathItems.add(new PathElementItem(propertyRef));
                }
                else {
                  final String path = VirtualFileManager.extractPath(url);
                  pathItems.add(new PathElementItem(
                    GenerationUtils.toRelativePath(path, chunk.getBaseDir(), moduleChunkBasedirProperty, genOptions)));
                }
              }
            }
            else {
              // Unknown order entry type. If it is actually encountered, extension point should be implemented
              pathItems.add(new GeneratorItem(orderEntry.getClass().getName(),
                                              new Comment("Unknown OrderEntryType: " + orderEntry.getClass().getName())));
            }
            return true;
          });
        }
      }.processModule(module, 0, false);
    }
    // convert path items to generators
    for (final ClasspathItem pathItem : pathItems) {
      add(pathItem.toGenerator());
    }
  }