@Override
  public VirtualFile[] getSourceRoots(Module module) {
    VirtualFile[] cachedRoots = myModuleToRootsCache.get(module);
    if (cachedRoots != null) {
      if (areFilesValid(cachedRoots)) {
        return cachedRoots;
      } else {
        myModuleToRootsCache.remove(
            module); // clear cache for this module and rebuild list of roots
      }
    }

    Set<VirtualFile> additionalRoots = myModuleToRootsMap.get(module);
    VirtualFile[] moduleRoots = ModuleRootManager.getInstance(module).getSourceRoots();
    if (additionalRoots == null || additionalRoots.isEmpty()) {
      myModuleToRootsCache.put(module, moduleRoots);
      return moduleRoots;
    }

    final VirtualFile[] allRoots = new VirtualFile[additionalRoots.size() + moduleRoots.length];
    System.arraycopy(moduleRoots, 0, allRoots, 0, moduleRoots.length);
    int index = moduleRoots.length;
    for (final VirtualFile additionalRoot : additionalRoots) {
      allRoots[index++] = additionalRoot;
    }
    myModuleToRootsCache.put(module, allRoots);
    return allRoots;
  }
 private String getOutputDir(final Module module) {
   if (myModuleToOutput.containsKey(module)) {
     return myModuleToOutput.get(module);
   }
   final VirtualFile outputDirectory = myCompileContext.getModuleOutputDirectory(module);
   final String out = outputDirectory != null ? outputDirectory.getPath() : null;
   myModuleToOutput.put(module, out);
   return out;
 }
    @Override
    public void save(DataOutput out) throws IOException {
      out.writeInt(myTimestamps.size());

      for (Map.Entry<String, Long> entry : myTimestamps.entrySet()) {
        out.writeUTF(entry.getKey());
        out.writeLong(entry.getValue());
      }
    }
 private VirtualFile getTempDir(Module module) throws IOException {
   VirtualFile tempDir = myModuleToTempDirMap.get(module);
   if (tempDir == null) {
     final String projectName = myProject.getName();
     final String moduleName = module.getName();
     File tempDirectory = FileUtil.createTempDirectory(projectName, moduleName);
     tempDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempDirectory);
     if (tempDir == null) {
       LOG.error("Cannot locate temp directory " + tempDirectory.getPath());
     }
     myModuleToTempDirMap.put(module, tempDir);
   }
   return tempDir;
 }
 @Override
 public void assignModule(
     @NotNull VirtualFile root,
     @NotNull Module module,
     final boolean isTestSource,
     @Nullable Compiler compiler) {
   try {
     myRootToModuleMap.put(root, module);
     Set<VirtualFile> set = myModuleToRootsMap.get(module);
     if (set == null) {
       set = new HashSet<VirtualFile>();
       myModuleToRootsMap.put(module, set);
     }
     set.add(root);
     if (isTestSource) {
       myGeneratedTestRoots.add(root);
     }
     if (compiler instanceof SourceGeneratingCompiler) {
       myOutputRootToSourceGeneratorMap.put(
           root,
           new Pair<SourceGeneratingCompiler, Module>(
               (SourceGeneratingCompiler) compiler, module));
     }
   } finally {
     myModuleToRootsCache.remove(module);
   }
 }
  public void compile() throws CompilerException, CacheCorruptedException {
    Application application = ApplicationManager.getApplication();
    try {
      if (!myFilesToCompile.isEmpty()) {
        if (application.isUnitTestMode()) {
          saveTestData();
        }
        compileModules(buildModuleToFilesMap(myFilesToCompile));
      }
    } catch (SecurityException e) {
      throw new CompilerException(
          CompilerBundle.message("error.compiler.process.not.started", e.getMessage()), e);
    } catch (IllegalArgumentException e) {
      throw new CompilerException(e.getMessage(), e);
    } finally {
      for (final VirtualFile file : myModuleToTempDirMap.values()) {
        if (file != null) {
          final File ioFile = new File(file.getPath());
          FileUtil.asyncDelete(ioFile);
        }
      }
      myModuleToTempDirMap.clear();
    }

    if (!myFilesToCompile.isEmpty()
        && myCompileContext.getMessageCount(CompilerMessageCategory.ERROR) == 0) {
      // package-info.java hack
      final List<TranslatingCompiler.OutputItem> outputs =
          new ArrayList<TranslatingCompiler.OutputItem>();
      ApplicationManager.getApplication()
          .runReadAction(
              new Runnable() {
                public void run() {
                  for (final VirtualFile file : myFilesToCompile) {
                    if (PACKAGE_ANNOTATION_FILE_NAME.equals(file.getName())
                        && !myProcessedPackageInfos.contains(file)) {
                      outputs.add(new OutputItemImpl(file));
                    }
                  }
                }
              });
      if (!outputs.isEmpty()) {
        mySink.add(null, outputs, VirtualFile.EMPTY_ARRAY);
      }
    }
  }
 @Override
 public Module getModuleByFile(VirtualFile file) {
   final Module module = myProjectFileIndex.getModuleForFile(file);
   if (module != null) {
     LOG.assertTrue(!module.isDisposed());
     return module;
   }
   for (final VirtualFile root : myRootToModuleMap.keySet()) {
     if (VfsUtil.isAncestor(root, file, false)) {
       final Module mod = myRootToModuleMap.get(root);
       if (mod != null) {
         LOG.assertTrue(!mod.isDisposed());
       }
       return mod;
     }
   }
   return null;
 }
    MyValidityState(DataInput in) throws IOException {
      final int size = in.readInt();

      for (int i = 0; i < size; i++) {
        final String path = in.readUTF();
        final long timestamp = in.readLong();

        myTimestamps.put(path, timestamp);
      }
    }
 @Override
 public boolean isInSourceContent(@NotNull final VirtualFile fileOrDir) {
   if (myProjectFileIndex.isInSourceContent(fileOrDir)
       || myProjectFileIndex.isInResource(fileOrDir)) {
     return true;
   }
   if (isUnderRoots(myRootToModuleMap.keySet(), fileOrDir)) {
     return true;
   }
   return false;
 }
  @NotNull
  private static String getPresentableFile(
      @NotNull String url, @Nullable Map<VirtualFile, VirtualFile> presentableFilesMap) {
    final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
    if (file == null) {
      return url;
    }

    if (presentableFilesMap == null) {
      return url;
    }

    for (Map.Entry<VirtualFile, VirtualFile> entry : presentableFilesMap.entrySet()) {
      if (file == entry.getValue()) {
        return entry.getKey().getUrl();
      }
    }
    return url;
  }
 @Override
 public boolean isGenerated(VirtualFile file) {
   if (myGeneratedSources.contains(FileBasedIndex.getFileId(file))) {
     return true;
   }
   if (isUnderRoots(myRootToModuleMap.keySet(), file)) {
     return true;
   }
   final Module module = getModuleByFile(file);
   if (module != null) {
     for (AdditionalOutputDirectoriesProvider provider :
         AdditionalOutputDirectoriesProvider.EP_NAME.getExtensions()) {
       for (String path : provider.getOutputDirectories(getProject(), module)) {
         if (path != null
             && VfsUtilCore.isAncestor(new File(path), new File(file.getPath()), true)) {
           return true;
         }
       }
     }
   }
   return false;
 }
  private void runTransformingCompilers(final ModuleChunk chunk) {
    final JavaSourceTransformingCompiler[] transformers =
        CompilerManager.getInstance(myProject).getCompilers(JavaSourceTransformingCompiler.class);
    if (transformers.length == 0) {
      return;
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("Running transforming compilers...");
    }
    final Module[] modules = chunk.getModules();
    for (final JavaSourceTransformingCompiler transformer : transformers) {
      final Map<VirtualFile, VirtualFile> originalToCopyFileMap =
          new HashMap<VirtualFile, VirtualFile>();
      final Application application = ApplicationManager.getApplication();
      application.invokeAndWait(
          new Runnable() {
            public void run() {
              for (final Module module : modules) {
                for (final VirtualFile file : chunk.getFilesToCompile(module)) {
                  final VirtualFile untransformed = chunk.getOriginalFile(file);
                  if (transformer.isTransformable(untransformed)) {
                    application.runWriteAction(
                        new Runnable() {
                          public void run() {
                            try {
                              // if untransformed != file, the file is already a (possibly
                              // transformed) copy of the original 'untransformed' file.
                              // If this is the case, just use already created copy and do not copy
                              // file content once again
                              final VirtualFile fileCopy =
                                  untransformed.equals(file)
                                      ? createFileCopy(getTempDir(module), file)
                                      : file;
                              originalToCopyFileMap.put(file, fileCopy);
                            } catch (IOException e) {
                              // skip it
                            }
                          }
                        });
                  }
                }
              }
            }
          },
          myCompileContext.getProgressIndicator().getModalityState());

      // do actual transform
      for (final Module module : modules) {
        final List<VirtualFile> filesToCompile = chunk.getFilesToCompile(module);
        for (int j = 0; j < filesToCompile.size(); j++) {
          final VirtualFile file = filesToCompile.get(j);
          final VirtualFile fileCopy = originalToCopyFileMap.get(file);
          if (fileCopy != null) {
            final boolean ok =
                transformer.transform(myCompileContext, fileCopy, chunk.getOriginalFile(file));
            if (ok) {
              chunk.substituteWithTransformedVersion(module, j, fileCopy);
            }
          }
        }
      }
    }
  }
 MyValidityState(@NotNull Collection<VirtualFile> files) {
   for (VirtualFile file : files) {
     myTimestamps.put(file.getPath(), file.getTimeStamp());
   }
 }