Package com.google.eclipse.protobuf.ui.util.editor

Source Code of com.google.eclipse.protobuf.ui.util.editor.ChangedLineRegionCalculator

/*
* Copyright (c) 2011 Google Inc.
*
* All rights reserved. This program and the accompanying materials are made available under the terms of the Eclipse
* Public License v1.0 which accompanies this distribution, and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package com.google.eclipse.protobuf.ui.util.editor;

import static org.eclipse.compare.rangedifferencer.RangeDifferencer.findDifferences;
import static org.eclipse.core.filebuffers.FileBuffers.createTextFileBufferManager;
import static org.eclipse.core.runtime.Status.OK_STATUS;
import static org.eclipse.core.runtime.SubProgressMonitor.PREPEND_MAIN_LABEL_TO_SUBTASK;

import static com.google.common.collect.Lists.newArrayList;
import static com.google.eclipse.protobuf.ui.util.IStatusFactory.error;
import static com.google.eclipse.protobuf.ui.util.editor.Messages.calculatingChangedRegions;
import static com.google.eclipse.protobuf.ui.util.editor.Messages.errorCalculatingChangedRegions;

import java.util.List;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.log4j.Logger;
import org.eclipse.compare.rangedifferencer.RangeDifference;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;

import com.google.inject.Singleton;

/**
* Utility methods related to editors. Adapted from CDT's
* {@code org.eclipse.cdt.internal.ui.util.EditorUtility}.
*
* @author alruiz@google.com (Alex Ruiz)
*/
@Singleton public class ChangedLineRegionCalculator {
  private static Logger logger = Logger.getLogger(ChangedLineRegionCalculator.class);

  public IRegion[] calculateChangedLineRegions(final ITextFileBuffer buffer, final IDocument current,
      final IProgressMonitor monitor) throws CoreException {
    final AtomicReference<IRegion[]> result = new AtomicReference<IRegion[]>();
    final AtomicReference<IStatus> errorStatus = new AtomicReference<IStatus>(OK_STATUS);
    try {
      SafeRunner.run(new ISafeRunnable() {
        @Override public void handleException(Throwable exception) {
          logger.error(exception.getMessage(), exception);
          errorStatus.set(error(errorCalculatingChangedRegions, exception));
          result.set(null);
        }

        @Override public void run() throws Exception {
          monitor.beginTask(calculatingChangedRegions, 20);
          IFileStore fileStore = buffer.getFileStore();
          ITextFileBufferManager fileBufferManager = createTextFileBufferManager();
          fileBufferManager.connectFileStore(fileStore, getSubProgressMonitor(monitor, 15));
          try {
            IDocument old = ((ITextFileBuffer) fileBufferManager.getFileStoreFileBuffer(fileStore)).getDocument();
            result.set(getChangedLineRegions(old));
          } finally {
            fileBufferManager.disconnectFileStore(fileStore, getSubProgressMonitor(monitor, 5));
            monitor.done();
          }
        }

        /*
         * Returns regions of all lines which differ comparing {@code old}s content with {@code current}s content.
         * Successive lines are merged into one region.
         */
        private IRegion[] getChangedLineRegions(IDocument old) {
          RangeDifference[] differences = differencesWith(old);
          List<IRegion> regions = newArrayList();
          int numberOfLines = current.getNumberOfLines();
          for (RangeDifference difference : differences) {
            if (difference.kind() == RangeDifference.CHANGE) {
              int startLine = Math.min(difference.rightStart(), numberOfLines - 1);
              int endLine = difference.rightEnd() - 1;
              IRegion startLineRegion;
              try {
                startLineRegion = current.getLineInformation(startLine);
                if (startLine >= endLine) {
                  // startLine > endLine indicates a deletion of one or more lines.
                  // Deletions are ignored except at the end of the document.
                  if (startLine == endLine
                      || startLineRegion.getOffset() + startLineRegion.getLength() == current.getLength()) {
                    regions.add(startLineRegion);
                  }
                  continue;
                }
                IRegion endLineRegion = current.getLineInformation(endLine);
                int startOffset = startLineRegion.getOffset();
                int endOffset = endLineRegion.getOffset() + endLineRegion.getLength();
                regions.add(new Region(startOffset, endOffset - startOffset));
              } catch (BadLocationException e) {
                logger.error(e.getMessage(), e);
              }
            }
          }
          return regions.toArray(new IRegion[regions.size()]);
        }

        private RangeDifference[] differencesWith(IDocument old) {
          return findDifferences(new LineComparator(old), new LineComparator(current));
        }
      });
    } finally {
      IStatus status = errorStatus.get();
      if (!status.isOK()) {
        throw new CoreException(status);
      }
    }
    return result.get();
  }

  private static IProgressMonitor getSubProgressMonitor(IProgressMonitor monitor, int ticks) {
    if (monitor != null) {
      return new SubProgressMonitor(monitor, ticks, PREPEND_MAIN_LABEL_TO_SUBTASK);
    }
    return new NullProgressMonitor();
  }
}
TOP

Related Classes of com.google.eclipse.protobuf.ui.util.editor.ChangedLineRegionCalculator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.