示例#1
0
  /** Result computed show it... Takes AnnotateLines and shows them. */
  public void annotationLines(File file, List<AnnotateLine> annotateLines) {
    // set repository root for popup menu, now should be the right time
    repositoryRoot = Mercurial.getInstance().getRepositoryRoot(getCurrentFile());
    final List<AnnotateLine> lines = new LinkedList<AnnotateLine>(annotateLines);
    int lineCount = lines.size();
    /** 0 based line numbers => 1 based line numbers */
    final int ann2editorPermutation[] = new int[lineCount];
    for (int i = 0; i < lineCount; i++) {
      ann2editorPermutation[i] = i + 1;
    }

    DiffProvider diff = (DiffProvider) Lookup.getDefault().lookup(DiffProvider.class);
    if (diff != null) {
      Reader r = new LinesReader(lines);
      Reader docReader = Utils.getDocumentReader(doc);
      try {

        Difference[] differences = diff.computeDiff(r, docReader);

        // customize annotation line numbers to match different reality
        // compule line permutation

        for (Difference d : differences) {
          int offset, editorStart;
          if (d.getType() == Difference.ADD) {
            offset = d.getSecondEnd() - d.getSecondStart() + 1;
            editorStart = d.getFirstStart();
          } else if (d.getType() == Difference.DELETE) {
            offset = d.getFirstEnd() - d.getFirstStart() + 1;
            editorStart = d.getFirstEnd();
            for (int c = editorStart - offset; c < editorStart; c++) {
              ann2editorPermutation[c] = -1;
            }
            offset = -offset;
          } else {
            // change
            int firstLen = d.getFirstEnd() - d.getFirstStart();
            int secondLen = d.getSecondEnd() - d.getSecondStart();
            offset = secondLen - firstLen;
            if (offset == 0) continue;
            editorStart = d.getFirstEnd();
            for (int c = d.getFirstStart(); c < editorStart; c++) {
              ann2editorPermutation[c] += -1;
            }
          }
          for (int c = editorStart; c < lineCount; c++) {
            ann2editorPermutation[c] += offset;
          }
        }

      } catch (IOException e) {
        Mercurial.LOG.log(
            Level.INFO,
            "Cannot compute local diff required for annotations, ignoring..."); // NOI18N
      }
    }

    doc.render(
        new Runnable() {
          @Override
          public void run() {
            StyledDocument sd = (StyledDocument) doc;
            Iterator<AnnotateLine> it = lines.iterator();
            previousRevisions = Collections.synchronizedMap(new HashMap<String, HgRevision>());
            originalFiles = Collections.synchronizedMap(new HashMap<String, File>());
            elementAnnotations =
                Collections.synchronizedMap(new HashMap<Element, AnnotateLine>(lines.size()));
            while (it.hasNext()) {
              AnnotateLine line = it.next();
              int lineNum = ann2editorPermutation[line.getLineNum() - 1];
              if (lineNum == -1) {
                continue;
              }
              try {
                int lineOffset = NbDocument.findLineOffset(sd, lineNum - 1);
                Element element = sd.getParagraphElement(lineOffset);
                elementAnnotations.put(element, line);
              } catch (IndexOutOfBoundsException ex) {
                // TODO how could I get line behind document end?
                // furtunately user does not spot it
                Mercurial.LOG.log(Level.INFO, null, ex);
              }
            }
          }
        });

    final String url = HgUtils.getRemoteRepository(repositoryRoot);
    final boolean isKenaiRepository = url != null && HgKenaiAccessor.getInstance().isKenai(url);
    if (isKenaiRepository) {
      kenaiUsersMap = new HashMap<String, KenaiUser>();
      Iterator<AnnotateLine> it = lines.iterator();
      while (it.hasNext()) {
        AnnotateLine line = it.next();
        String author = line.getAuthor();
        if (author != null && !author.equals("") && !kenaiUsersMap.keySet().contains(author)) {
          KenaiUser ku = HgKenaiAccessor.getInstance().forName(author, url);
          if (ku != null) {
            kenaiUsersMap.put(author, ku);
          }
        }
      }
    }

    // lazy listener registration
    caret.addChangeListener(this);
    this.caretTimer = new Timer(500, this);
    caretTimer.setRepeats(false);

    elementAnnotationsSubstitute = "";
    onCurrentLine();
    revalidate();
    repaint();
  }
  @Override
  public Map<String, List<OffsetRange>> folds(ParserResult info) {
    ASTNode root = ASTUtils.getRoot(info);

    if (root == null) {
      return Collections.emptyMap();
    }

    GroovyParserResult rpr = ASTUtils.getParseResult(info);
    AnalysisResult analysisResult = rpr.getStructure();

    Map<String, List<OffsetRange>> folds = new HashMap<String, List<OffsetRange>>();
    List<OffsetRange> codefolds = new ArrayList<OffsetRange>();
    folds.put("codeblocks", codefolds); // NOI18N

    final BaseDocument doc = LexUtilities.getDocument(rpr, false);
    if (doc == null) {
      return Collections.emptyMap();
    }

    final OffsetRange[] importsRange = new OffsetRange[1];
    final List<OffsetRange> commentsRanges = new ArrayList<OffsetRange>();

    doc.render(
        new Runnable() {
          @Override
          public void run() {
            TokenSequence<?> ts = LexUtilities.getGroovyTokenSequence(doc, 1);

            int importStart = 0;
            int importEnd = 0;

            boolean startSet = false;

            while (ts != null && ts.isValid() && ts.moveNext()) {
              Token t = ts.token();
              if (t.id() == GroovyTokenId.LITERAL_import) {
                int offset = ts.offset();
                if (!startSet) {
                  importStart = offset;
                  startSet = true;
                }
                importEnd = offset;
              } else if (t.id() == GroovyTokenId.BLOCK_COMMENT) {
                // does this Block comment (GSF_BLOCK_COMMENT) span
                // multiple lines? E.g. includes \n ?
                StringBuffer sb = new StringBuffer(t.text());

                if (sb.indexOf("\n") != -1) {
                  int offset = ts.offset();
                  commentsRanges.add(new OffsetRange(offset, offset + t.length()));
                }
              }
            }
            try {
              importEnd = Utilities.getRowEnd(doc, importEnd);
              importsRange[0] = new OffsetRange(importStart, importEnd);
            } catch (BadLocationException ble) {
              Exceptions.printStackTrace(ble);
            }
          }
        });

    if (!commentsRanges.isEmpty()) {
      folds.put("comments", commentsRanges); // NOI18N
    }

    try {
      if (importsRange[0] != null
          && Utilities.getRowCount(doc, importsRange[0].getStart(), importsRange[0].getEnd()) > 1) {
        folds.put("imports", Collections.singletonList(importsRange[0])); // NOI18N
      }
      addFolds(doc, analysisResult.getElements(), folds, codefolds);
    } catch (BadLocationException ex) {
      Exceptions.printStackTrace(ex);
    }

    return folds;
  }