blob: c6150326a30939f8cbfe42f9c4bfea4a17bf5983 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2018 1C-Soft LLC.
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Vladimir Piskarev (1C) - initial API and implementation
*******************************************************************************/
package org.eclipse.handly.ui.text.reconciler;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.handly.model.Elements;
import org.eclipse.handly.model.ISourceFile;
import org.eclipse.handly.ui.IWorkingCopyManager;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
/**
* Reconciles a working copy.
*/
public class WorkingCopyReconcilingStrategy
implements IReconcilingStrategy, IReconcilingStrategyExtension
{
private final IWorkingCopyManager workingCopyManager;
private volatile ISourceFile workingCopy;
private volatile IProgressMonitor monitor;
/**
* Creates a new working copy reconciling strategy with the given
* working copy manager. The working copy manager is used to determine
* the working copy for the reconciling strategy's document.
*
* @param workingCopyManager not <code>null</code>
*/
public WorkingCopyReconcilingStrategy(
IWorkingCopyManager workingCopyManager)
{
if (workingCopyManager == null)
throw new IllegalArgumentException();
this.workingCopyManager = workingCopyManager;
}
@Override
public void setDocument(IDocument document)
{
setWorkingCopy(workingCopyManager.getWorkingCopy(document));
}
@Override
public void setProgressMonitor(IProgressMonitor monitor)
{
this.monitor = monitor;
}
/**
* {@inheritDoc}
* <p>
* This implementation delegates to {@link #reconcile(ISourceFile, boolean,
* IProgressMonitor)}, passing the working copy for the reconciling strategy's
* document and indicating that this is the initial reconcile; any exceptions
* are logged and not rethrown.
* </p>
*/
@Override
public final void initialReconcile()
{
reconcile(true);
}
/**
* {@inheritDoc}
* <p>
* This implementation delegates to {@link #reconcile(ISourceFile, boolean,
* IProgressMonitor)}, passing the working copy for the reconciling strategy's
* document; any exceptions are logged and not rethrown.
* </p>
*/
@Override
public final void reconcile(DirtyRegion dirtyRegion, IRegion subRegion)
{
reconcile(false);
}
/**
* {@inheritDoc}
* <p>
* This implementation delegates to {@link #reconcile(ISourceFile, boolean,
* IProgressMonitor)}, passing the working copy for the reconciling strategy's
* document; any exceptions are logged and not rethrown.
* </p>
*/
@Override
public final void reconcile(IRegion partition)
{
reconcile(false);
}
/**
* Reconciles the given working copy.
* <p>
* This implementation invokes <code>Elements.{@link Elements#reconcile(ISourceFile,
* IProgressMonitor) reconcile}(workingCopy, monitor)</code>.
* </p>
*
* @param workingCopy never <code>null</code>
* @param initialReconcile <code>true</code> if this is the initial reconcile,
* and <code>false</code> otherwise
* @param monitor a progress monitor, or <code>null</code>
* if progress reporting is not desired. The caller must not rely on
* {@link IProgressMonitor#done()} having been called by the receiver
* @throws CoreException if the working copy could not be reconciled
* @throws OperationCanceledException if this method is canceled
*/
protected void reconcile(ISourceFile workingCopy, boolean initialReconcile,
IProgressMonitor monitor) throws CoreException
{
Elements.reconcile(workingCopy, monitor);
}
private void reconcile(boolean initialReconcile)
{
ISourceFile workingCopy = getWorkingCopy();
if (workingCopy == null)
return;
SafeRunner.run(new ISafeRunnable()
{
public void run() throws Exception
{
reconcile(workingCopy, initialReconcile, monitor);
}
public void handleException(Throwable exception)
{
// already logged by Platform
}
});
}
private void setWorkingCopy(ISourceFile workingCopy)
{
this.workingCopy = workingCopy;
}
private ISourceFile getWorkingCopy()
{
return workingCopy;
}
}