/**
   * Updates the occurrences annotations based on the current selection.
   *
   * @param selection the text selection
   * @param module
   * @param astRoot the compilation unit AST
   * @since 3.0
   */
  protected void updateOccurrenceAnnotations(
      final ITextSelection selection, final IErlModule module) {

    if (fOccurrencesFinderJob != null) {
      fOccurrencesFinderJob.cancel();
    }

    if (!fMarkOccurrenceAnnotations) {
      return;
    }

    if (module == null || selection == null) {
      return;
    }

    final IDocument document = erlangEditor.getViewer().getDocument();
    if (document == null) {
      return;
    }

    boolean hasChanged = false;
    final int offset = selection.getOffset();
    if (document instanceof IDocumentExtension4) {
      final long currentModificationStamp = ((IDocumentExtension4) document).getModificationStamp();
      final IRegion markOccurrenceTargetRegion = fMarkOccurrenceTargetRegion;
      hasChanged = currentModificationStamp != fMarkOccurrenceModificationStamp;
      if (markOccurrenceTargetRegion != null && !hasChanged) {
        if (markOccurrenceTargetRegion.getOffset() <= offset
            && offset
                <= markOccurrenceTargetRegion.getOffset()
                    + markOccurrenceTargetRegion.getLength()) {
          return;
        }
      }
      fMarkOccurrenceTargetRegion = ErlangWordFinder.findWord(module, erlangEditor, offset);
      fMarkOccurrenceModificationStamp = currentModificationStamp;
    }

    if (fOccurrencesFinderJob != null) {
      fOccurrencesFinderJob.cancel();
    }
    fOccurrencesFinderJob = new OccurrencesFinderJob(document, module, selection, hasChanged);
    fOccurrencesFinderJob.setPriority(Job.DECORATE);
    fOccurrencesFinderJob.setSystem(true);
    fOccurrencesFinderJob.schedule();
    // fOccurrencesFinderJob.run(new NullProgressMonitor());
  }
  protected void uninstallOccurrencesFinder() {
    fMarkOccurrenceAnnotations = false;

    if (fOccurrencesFinderJob != null) {
      fOccurrencesFinderJob.cancel();
      fOccurrencesFinderJob = null;
    }

    if (fOccurrencesFinderJobCanceler != null) {
      fOccurrencesFinderJobCanceler.uninstall();
      fOccurrencesFinderJobCanceler = null;
    }

    if (fPostSelectionListenerWithAST != null) {
      SelectionListenerWithASTManager.getDefault()
          .removeListener(editor, fPostSelectionListenerWithAST);
      fPostSelectionListenerWithAST = null;
    }

    removeOccurrenceAnnotations();
  }
  protected void uninstallOccurrencesFinder() {
    fMarkOccurrenceAnnotations = false;

    if (fOccurrencesFinderJob != null) {
      fOccurrencesFinderJob.cancel();
      fOccurrencesFinderJob = null;
    }

    if (fOccurrencesFinderJobCanceler != null) {
      fOccurrencesFinderJobCanceler.uninstall();
      fOccurrencesFinderJobCanceler = null;
    }

    if (fPostSelectionListener != null) {
      ((IPostSelectionProvider) erlangEditor.getSelectionProvider())
          .removePostSelectionChangedListener(fPostSelectionListener);
      fPostSelectionListener = null;
    }

    erlangEditor.markOccurencesHandler.removeOccurrenceAnnotations();
  }
  /**
   * Updates the occurrences annotations based on the current selection.
   *
   * @param selection The text selection
   * @param ast An AST
   */
  protected void updateOccurrenceAnnotations(ITextSelection selection, Program ast) {
    if (fOccurrencesFinderJob != null) fOccurrencesFinderJob.cancel();

    if (!fMarkOccurrenceAnnotations) return;

    if (ast == null || selection == null) return;
    if (!ast.isBindingCompleted()) {
      TypeBindingBuilder.buildBindings(ast);
    }
    IDocument document = editor.getISourceViewer().getDocument();
    if (document == null) return;

    // TODO: Shalom - Replace this to do a real check whether this script was already reconciled
    if (document.getLength() != ast.getEnd()) {
      return;
    }

    boolean hasChanged = false;
    if (document instanceof IDocumentExtension4) {
      int offset = selection.getOffset();
      long currentModificationStamp = ((IDocumentExtension4) document).getModificationStamp();
      IRegion markOccurrenceTargetRegion = fMarkOccurrenceTargetRegion;
      hasChanged = currentModificationStamp != fMarkOccurrenceModificationStamp;
      if (markOccurrenceTargetRegion != null && !hasChanged) {
        if (markOccurrenceTargetRegion.getOffset() <= offset
            && offset
                <= markOccurrenceTargetRegion.getOffset() + markOccurrenceTargetRegion.getLength())
          return;
      }
      fMarkOccurrenceTargetRegion = ScriptWordFinder.findWord(document, offset);
      fMarkOccurrenceModificationStamp = currentModificationStamp;
    }

    OccurrenceLocation[] locations = null;

    ASTNode selectedNode = NodeFinder.perform(ast, selection.getOffset(), selection.getLength());

    // if (locations == null && fMarkExceptions)
    // {
    // TODO: Shalom - Implement
    // }

    if (locations == null && fMarkMethodExitPoints) {
      IOccurrencesFinder finder = OccurrencesFinderFactory.createMethodExitsFinder();
      if (finder.initialize(ast, selectedNode) == null) {
        locations = finder.getOccurrences();
      }
    }

    if (locations == null && fMarkImplementors) {
      IOccurrencesFinder finder = OccurrencesFinderFactory.createIncludeFinder();
      if (finder.initialize(ast, selectedNode) == null) {
        locations = finder.getOccurrences();
      }
    }

    if (locations == null && fMarkBreakContinueTargets) {
      IOccurrencesFinder finder = OccurrencesFinderFactory.createBreakContinueTargetFinder();
      if (finder.initialize(ast, selectedNode) == null) {
        locations = finder.getOccurrences();
      }
    }

    if (locations == null && fMarkImplementors) {
      IOccurrencesFinder finder = OccurrencesFinderFactory.createImplementorsOccurrencesFinder();
      if (finder.initialize(ast, selectedNode) == null) {
        locations = finder.getOccurrences();
      }
    }

    if (selectedNode != null && selectedNode.getType() == ASTNode.VARIABLE) {
      final Expression name = ((Variable) selectedNode).getName();
      if (name instanceof Identifier) {
        selectedNode = name;
      }
    }

    if (locations == null
        && selectedNode != null
        && (selectedNode instanceof Identifier || (isNonStringScalar(selectedNode)))) {
      int type = PhpElementConciliator.concile(selectedNode);
      if (isMarkingOccurrencesFor(type)) {
        IOccurrencesFinder finder = OccurrencesFinderFactory.getOccurrencesFinder(type);
        if (finder != null) {
          if (finder.initialize(ast, selectedNode) == null) {
            locations = finder.getOccurrences();
          }
        }
      }
    }

    if (locations == null) {
      if (!fStickyOccurrenceAnnotations) {
        removeOccurrenceAnnotations();
      } else if (hasChanged) // check consistency of current annotations
      {
        removeOccurrenceAnnotations();
      }
      return;
    }

    fOccurrencesFinderJob = new OccurrencesFinderJob(document, locations, selection);
    fOccurrencesFinderJob.setPriority(Job.DECORATE);
    fOccurrencesFinderJob.schedule();
  }