IStatus performNavigation(IProgressMonitor monitor) throws CoreException {
    fAction.clearStatusLine();

    assert fIndex == null;
    if (fIndex != null) return Status.CANCEL_STATUS;

    fMonitor = monitor;
    fIndex =
        CCorePlugin.getIndexManager()
            .getIndex(
                fTranslationUnit.getCProject(),
                IIndexManager.ADD_DEPENDENCIES | IIndexManager.ADD_DEPENDENT);

    try {
      fIndex.acquireReadLock();
    } catch (InterruptedException e) {
      return Status.CANCEL_STATUS;
    }

    try {
      return ASTProvider.getASTProvider()
          .runOnAST(fTranslationUnit, ASTProvider.WAIT_ACTIVE_ONLY, monitor, this);
    } finally {
      fIndex.releaseReadLock();
    }
  }
  private void openInclude(IASTPreprocessorIncludeStatement incStmt) {
    String name = null;
    if (incStmt.isResolved()) name = incStmt.getPath();

    if (name != null) {
      final IPath path = new Path(name);
      runInUIThread(
          new Runnable() {
            public void run() {
              try {
                fAction.open(path, 0, 0);
              } catch (CoreException e) {
                CUIPlugin.log(e);
              }
            }
          });
    } else {
      fAction.reportIncludeLookupFailure(new String(incStmt.getName().toCharArray()));
    }
  }
  public IStatus runOnAST(ILanguage lang, IASTTranslationUnit ast) throws CoreException {
    if (ast == null) {
      return Status.OK_STATUS;
    }
    int selectionStart = fTextSelection.getOffset();
    int selectionLength = fTextSelection.getLength();

    final IASTNodeSelector nodeSelector = ast.getNodeSelector(null);

    IASTName sourceName = nodeSelector.findEnclosingName(selectionStart, selectionLength);
    IName[] implicitTargets =
        findImplicitTargets(ast, nodeSelector, selectionStart, selectionLength);
    if (sourceName == null) {
      if (implicitTargets.length > 0) {
        if (navigateViaCElements(fTranslationUnit.getCProject(), fIndex, implicitTargets))
          return Status.OK_STATUS;
      }
    } else {
      boolean found = false;
      final IASTNode parent = sourceName.getParent();
      if (parent instanceof IASTPreprocessorIncludeStatement) {
        openInclude(((IASTPreprocessorIncludeStatement) parent));
        return Status.OK_STATUS;
      }
      NameKind kind = getNameKind(sourceName);
      IBinding b = sourceName.resolveBinding();
      IBinding[] bindings = new IBinding[] {b};
      if (b instanceof IProblemBinding) {
        IBinding[] candidateBindings = ((IProblemBinding) b).getCandidateBindings();
        if (candidateBindings.length != 0) {
          bindings = candidateBindings;
        }
      } else if (kind == NameKind.DEFINITION && b instanceof IType) {
        // Don't navigate away from a type definition.
        // Select the name at the current location instead.
        navigateToName(sourceName);
        return Status.OK_STATUS;
      }
      IName[] targets = IName.EMPTY_ARRAY;
      String filename = ast.getFilePath();
      for (IBinding binding : bindings) {
        if (binding != null && !(binding instanceof IProblemBinding)) {
          IName[] names = findDeclNames(ast, kind, binding);
          for (final IName name : names) {
            if (name != null) {
              if (name instanceof IIndexName
                  && filename.equals(((IIndexName) name).getFileLocation().getFileName())) {
                // Exclude index names from the current file.
              } else if (areOverlappingNames(name, sourceName)) {
                // Exclude the current location.
              } else if (binding instanceof IParameter) {
                if (isInSameFunction(sourceName, name)) {
                  targets = ArrayUtil.append(targets, name);
                }
              } else if (binding instanceof ICPPTemplateParameter) {
                if (isInSameTemplate(sourceName, name)) {
                  targets = ArrayUtil.append(targets, name);
                }
              } else {
                targets = ArrayUtil.append(targets, name);
              }
            }
          }
        }
      }
      targets = ArrayUtil.trim(ArrayUtil.addAll(targets, implicitTargets));
      if (navigateViaCElements(fTranslationUnit.getCProject(), fIndex, targets)) {
        found = true;
      } else {
        // Leave old method as fallback for local variables, parameters and
        // everything else not covered by ICElementHandle.
        found = navigateOneLocation(targets);
      }
      if (!found && !navigationFallBack(ast, sourceName, kind)) {
        fAction.reportSymbolLookupFailure(new String(sourceName.toCharArray()));
      }
      return Status.OK_STATUS;
    }

    // No enclosing name, check if we're in an include statement
    IASTNode node = nodeSelector.findEnclosingNode(selectionStart, selectionLength);
    if (node instanceof IASTPreprocessorIncludeStatement) {
      openInclude((IASTPreprocessorIncludeStatement) node);
      return Status.OK_STATUS;
    } else if (node instanceof IASTPreprocessorFunctionStyleMacroDefinition) {
      IASTPreprocessorFunctionStyleMacroDefinition mdef =
          (IASTPreprocessorFunctionStyleMacroDefinition) node;
      for (IASTFunctionStyleMacroParameter par : mdef.getParameters()) {
        String parName = par.getParameter();
        if (parName.equals(fSelectedText)) {
          if (navigateToLocation(par.getFileLocation())) {
            return Status.OK_STATUS;
          }
        }
      }
    }
    if (!navigationFallBack(ast, null, NameKind.REFERENCE)) {
      fAction.reportSelectionMatchFailure();
    }
    return Status.OK_STATUS;
  }