private void parseVersionInContext(
      int linkageID,
      LinkageTask map,
      IIndexFileLocation ifl,
      final FileVersionTask versionTask,
      Object tu,
      LinkedHashSet<IIndexFile> safeGuard,
      IProgressMonitor monitor)
      throws CoreException, InterruptedException {
    final IIndexFragmentFile headerFile = versionTask.fIndexFile;

    final int safeguardSize = safeGuard.size();
    while (true) {
      // Look for a context and parse the file.
      IIndexFragmentFile ctxFile = findContextFile(linkageID, map, versionTask, safeGuard, monitor);
      if (ctxFile == null || ctxFile == headerFile) return;

      Object contextTu = fResolver.getInputFile(ctxFile.getLocation());
      if (contextTu == null) return;

      final IScannerInfo scannerInfo = getScannerInfo(linkageID, contextTu);
      final AbstractLanguage language = getLanguage(contextTu, linkageID);
      final FileContext ctx = new FileContext(ctxFile, headerFile);
      Set<IIndexFile> dependencies = null;
      boolean done = false;
      while (!done) {
        done = true;
        DependsOnOutdatedFileException d = parseFile(tu, language, ifl, scannerInfo, ctx, monitor);
        if (d != null) {
          // File was not parsed, because there is a dependency that needs to be
          // handled before.
          if (dependencies == null) dependencies = new HashSet<IIndexFile>();
          if (dependencies.add(d.fIndexFile)) {
            if (parseFile(
                    d.fTu,
                    language,
                    d.fIndexFile.getLocation(),
                    scannerInfo,
                    new FileContext(ctxFile, d.fIndexFile),
                    monitor)
                == null) done = false;
          }
        }
      }
      if (!ctx.fLostPragmaOnceSemantics) return;

      // Try the next context
      restoreSet(safeGuard, safeguardSize);
    }
  }
  @Override
  public void clearFile(IIndexFragmentFile file) throws CoreException {
    assert file.getIndexFragment() == this;
    IIndexFileLocation location = file.getLocation();
    PDOMFile pdomFile = (PDOMFile) file;
    pdomFile.clear();
    IIndexInclude include = pdomFile.getParsedInContext();
    if (include != null) {
      PDOMFile includedBy = (PDOMFile) include.getIncludedBy();
      if (includedBy.getTimestamp() > 0)
        getIndexOfFilesWithUnresolvedIncludes().insert(includedBy.getRecord());
    }

    fEvent.fClearedFiles.add(location);
  }
  @Override
  public void addFileContent(
      IIndexFragmentFile sourceFile,
      IncludeInformation[] includes,
      IASTPreprocessorStatement[] macros,
      IASTName[][] names,
      ASTFilePathResolver pathResolver,
      YieldableIndexLock lock)
      throws CoreException, InterruptedException {
    assert sourceFile.getIndexFragment() == this;

    PDOMFile pdomFile = (PDOMFile) sourceFile;
    pdomFile.addMacros(macros);
    final ASTFilePathResolver origResolver = fPathResolver;
    fPathResolver = pathResolver;
    try {
      pdomFile.addNames(names, lock);
    } finally {
      fPathResolver = origResolver;
    }
    // Includes expose the temporary file in the index, we must not yield the lock beyond this
    // point.
    pdomFile.addIncludesTo(includes);

    final IIndexFileLocation location = pdomFile.getLocation();
    if (location != null) {
      fEvent.fClearedFiles.remove(location);
      fEvent.fFilesWritten.add(location);
    }
  }
 private boolean isModified(
     boolean checkTimestamps,
     boolean checkFileContentsHash,
     IIndexFileLocation ifl,
     Object tu,
     IIndexFragmentFile file)
     throws CoreException {
   if (checkTimestamps) {
     if (fResolver.getLastModified(ifl) != file.getTimestamp()
         || computeFileSizeAndEncodingHashcode(ifl) != file.getSizeAndEncodingHashcode()) {
       if (checkFileContentsHash && computeFileContentsHash(tu) == file.getContentsHash()) {
         return false;
       }
       return true;
     }
   }
   return false;
 }
  IIndexFragmentFile selectIndexFile(
      int linkageID, IIndexFileLocation ifl, ISignificantMacros sigMacros) throws CoreException {
    LinkageTask map = findRequestMap(linkageID);
    if (map != null) {
      LocationTask locTask = map.find(ifl);
      if (locTask != null) {
        FileVersionTask task = locTask.findVersion(sigMacros);
        if (task != null) {
          return task.fOutdated ? null : task.fIndexFile;
        }
      }
    }

    IIndexFragmentFile[] files = getAvailableIndexFiles(linkageID, ifl);
    for (IIndexFragmentFile file : files) {
      if (sigMacros.equals(file.getSignificantMacros())) return file;
    }
    return null;
  }
  private IIndexFragmentFile findContextFile(
      int linkageID,
      LinkageTask map,
      final FileVersionTask versionTask,
      LinkedHashSet<IIndexFile> safeGuard,
      IProgressMonitor monitor)
      throws CoreException, InterruptedException {
    IIndexFragmentFile ctxFile = versionTask.fIndexFile;
    while (true) {
      IIndexInclude ctxInclude = ctxFile.getParsedInContext();
      if (ctxInclude == null) return ctxFile;

      IIndexFragmentFile nextCtx = (IIndexFragmentFile) ctxInclude.getIncludedBy();
      if (nextCtx == null) return nextCtx;

      // Found a recursion.
      if (!safeGuard.add(nextCtx)) return null;

      final IIndexFileLocation ctxIfl = nextCtx.getLocation();
      LocationTask ctxTask = map.find(ctxIfl);
      if (ctxTask != null) {
        FileVersionTask ctxVersionTask = ctxTask.findVersion(nextCtx);
        if (ctxVersionTask != null && ctxVersionTask.fOutdated) {
          // Handle the context first.
          parseVersionInContext(
              linkageID, map, ctxIfl, ctxVersionTask, ctxTask.fTu, safeGuard, monitor);
          if (ctxVersionTask.fOutdated // This is unexpected.
              || !versionTask.fOutdated) // Our file was parsed.
          return null;

          // The file is no longer a context, look for a different one.
          nextCtx = ctxFile;
        }
      }
      ctxFile = nextCtx;
    }
  }
  private void extractFiles(
      HashMap<Integer, List<IIndexFileLocation>> files,
      List<IIndexFragmentFile> iFilesToRemove,
      IProgressMonitor monitor)
      throws CoreException {
    final boolean forceAll = (fUpdateFlags & IIndexManager.UPDATE_ALL) != 0;
    final boolean checkTimestamps = (fUpdateFlags & IIndexManager.UPDATE_CHECK_TIMESTAMPS) != 0;
    final boolean checkFileContentsHash =
        (fUpdateFlags & IIndexManager.UPDATE_CHECK_CONTENTS_HASH) != 0;
    final boolean forceUnresolvedIncludes =
        (fUpdateFlags & IIndexManager.UPDATE_UNRESOLVED_INCLUDES) != 0;
    final boolean both = fIndexHeadersWithoutContext == UnusedHeaderStrategy.useBoth;
    int count = 0;
    int forceFirst = fForceNumberFiles;
    BitSet linkages = new BitSet();
    for (final Object tu : fFilesToUpdate) {
      if (monitor.isCanceled()) return;

      final boolean force = forceAll || --forceFirst >= 0;
      final IIndexFileLocation ifl = fResolver.resolveFile(tu);
      if (ifl == null) continue;

      final IIndexFragmentFile[] indexFiles = fIndex.getWritableFiles(ifl);
      final boolean isSourceUnit = fResolver.isSourceUnit(tu);
      linkages.clear();
      final boolean regularContent = isRequiredInIndex(tu, ifl, isSourceUnit);
      final boolean indexedUnconditionally = fResolver.isIndexedUnconditionally(ifl);
      if (regularContent || indexedUnconditionally) {
        // Headers or sources required with a specific linkage
        final UpdateKind updateKind =
            isSourceUnit
                ? UpdateKind.REQUIRED_SOURCE
                : regularContent && both
                    ? UpdateKind.REQUIRED_HEADER
                    : UpdateKind.ONE_LINKAGE_HEADER;
        if (regularContent || indexFiles.length == 0) {
          AbstractLanguage[] langs = fResolver.getLanguages(tu, fIndexHeadersWithoutContext);
          for (AbstractLanguage lang : langs) {
            int linkageID = lang.getLinkageID();
            boolean foundInLinkage = false;
            for (int i = 0; i < indexFiles.length; i++) {
              IIndexFragmentFile ifile = indexFiles[i];
              if (ifile != null && ifile.getLinkageID() == linkageID && ifile.hasContent()) {
                foundInLinkage = true;
                indexFiles[i] = null; // Take the file.
                boolean update =
                    force
                        || (forceUnresolvedIncludes && ifile.hasUnresolvedInclude())
                        || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
                if (update && requestUpdate(linkageID, ifl, ifile, tu, updateKind)) {
                  count++;
                  linkages.set(linkageID);
                }
              }
            }
            if (!foundInLinkage && requestUpdate(linkageID, ifl, null, tu, updateKind)) {
              linkages.set(linkageID);
              count++;
            }
          }
        }
      }

      // Handle other files present in index.
      for (IIndexFragmentFile ifile : indexFiles) {
        if (ifile != null) {
          IIndexInclude ctx = ifile.getParsedInContext();
          if (ctx == null && !indexedUnconditionally && ifile.hasContent()) {
            iFilesToRemove.add(ifile);
            count++;
          } else {
            boolean update =
                force
                    || (forceUnresolvedIncludes && ifile.hasUnresolvedInclude())
                    || isModified(checkTimestamps, checkFileContentsHash, ifl, tu, ifile);
            final int linkageID = ifile.getLinkageID();
            if (update && requestUpdate(linkageID, ifl, ifile, tu, UpdateKind.OTHER_HEADER)) {
              count++;
              linkages.set(linkageID);
            }
          }
        }
      }
      for (int lid = linkages.nextSetBit(0); lid >= 0; lid = linkages.nextSetBit(lid + 1)) {
        addPerLinkage(lid, ifl, files);
      }
    }
    synchronized (this) {
      incrementRequestedFilesCount(count - fFilesToUpdate.length);
      fFilesToUpdate = null;
    }
  }