/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * 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 * * Contributors: * IBM Corporation - initial API and implementation * Zend Technologies *******************************************************************************/ package org.eclipse.php.internal.ui.editor.configuration; import org.eclipse.core.runtime.Assert; import org.eclipse.jface.text.*; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.jface.text.rules.RuleBasedScanner; import org.eclipse.php.internal.core.documentModel.parser.PHPRegionContext; import org.eclipse.php.internal.core.documentModel.parser.regions.IPHPScriptRegion; import org.eclipse.php.internal.ui.editor.highlighter.LineStyleProviderForPHP; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion; import org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider; import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider; public class StructuredDocumentDamagerRepairer extends DefaultDamagerRepairer { private LineStyleProvider fProvider = null; public StructuredDocumentDamagerRepairer(LineStyleProvider provider) { super(new RuleBasedScanner()); Assert.isNotNull(provider); fProvider = provider; } /** * Returns presentation which covers only updated php tokens in case when * the damage covers whole PHP region and this regions has not been fully * reparsed. * * @param region * @param damage * @return presentation or null - if region has been fully reparsed */ public TextPresentation getPresentation(ITypedRegion region, IRegion damage) { if (fProvider instanceof LineStyleProviderForPHP) { IStructuredDocumentRegion structuredDocumentRegion = ((LineStyleProviderForPHP) fProvider) .getDamagedRegion(region); ITextRegion textReg = structuredDocumentRegion.getRegionAtCharacterOffset(region.getOffset()); if (textReg != null && textReg.getType() == PHPRegionContext.PHP_CONTENT && damageCoversWholeRegion(region, textReg, damage)) { IPHPScriptRegion phpScriptRegion = (IPHPScriptRegion) textReg; if (!phpScriptRegion.isFullReparsed()) { Region r = new Region(phpScriptRegion.getUpdatedTokensStart() + region.getOffset(), phpScriptRegion.getUpdatedTokensLength()); return new TextPresentation((IRegion) r, 1000); } } } return null; } private boolean damageCoversWholeRegion(ITypedRegion originalRegion, ITextRegion textRegion, IRegion damage) { // if php content region is bigger than actual damaged // region if ((textRegion.getLength() == originalRegion.getLength()) && (textRegion.getStart() < originalRegion.getOffset())) { if ((originalRegion.getOffset() == damage.getOffset()) && (originalRegion.getLength() == damage.getLength())) { return true; } } else if ((textRegion.getStart() == damage.getOffset()) && (textRegion.getLength() == damage.getLength())) { return true; } return false; } @Override public void createPresentation(TextPresentation presentation, ITypedRegion region) { // https://bugs.eclipse.org/bugs/show_bug.cgi?id=491328 // Workaround for bug 491328: // Method // PHPStructuredTextViewerConfiguration.getPresentationReconciler(ISourceViewer) // returns a *new* PHPStructuredPresentationReconciler object // containing a list of *new* StructuredDocumentDamagerRepairer // objects for each *shared* LineStyleProvider object retrieved by // method ReconcilerHighlighter.getProvider(String) and method // PHPStructuredTextViewerConfiguration.getConfiguredContentTypes(ISourceViewer). // Every thread initialized with // PHPStructuredTextViewerConfiguration.getPresentationReconciler(ISourceViewer) // will then work with their own instances of // PHPStructuredPresentationReconciler and // StructuredDocumentDamagerRepairer objects BUT will share same // LineStyleProvider instance per content type, which can be // problematic when multiple threads have simultaneous access to those // shared LineStyleProvider objects. // Since class LineStyleProvider isn't designed to be thread-safe for // now, we protect at least concurrent access to // main method LineStyleProvider.prepareRegions(...). // Of course, it doesn't protect places where // LineStyleProvider.prepareRegions(...) is called directly, like in // Highlighter.prepareStyleRangesArray(...). synchronized (fProvider) { PresentationCollector collector = new PresentationCollector(presentation); fProvider.prepareRegions(region, region.getOffset(), region.getLength(), collector); } } public void setProvider(LineStyleProvider provider) { fProvider = provider; } @Override public void setDocument(IDocument document) { super.setDocument(document); if (fProvider instanceof AbstractLineStyleProvider) ((AbstractLineStyleProvider) fProvider).setDocument((IStructuredDocument) document); } }