package com.google.dart.tools.wst.ui.style; import com.google.dart.tools.internal.corext.refactoring.util.ReflectionUtils; import com.google.dart.tools.ui.internal.text.dart.DartCodeScanner; import com.google.dart.tools.ui.internal.text.dartdoc.DartDocScanner; import com.google.dart.tools.ui.internal.text.functions.DartCommentScanner; import com.google.dart.tools.ui.internal.text.functions.DartMultilineStringScanner; import com.google.dart.tools.ui.internal.text.functions.SingleTokenDartScanner; import com.google.dart.tools.ui.text.DartIndiscriminateDamager; import com.google.dart.tools.ui.text.DartPartitions; import com.google.dart.tools.ui.text.IColorManager; import com.google.dart.tools.ui.text.IDartColorConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextPresentation; import org.eclipse.jface.text.TextUtilities; import org.eclipse.jface.text.presentation.IPresentationDamager; import org.eclipse.jface.text.presentation.IPresentationRepairer; import org.eclipse.jface.text.rules.DefaultDamagerRepairer; import org.eclipse.swt.custom.StyleRange; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; /** * Analyze a document to produce syntactic highlighting ranges. Adapted from PresentationReconciler. */ public class SyntacticHighlightingEngine { private static class PositionCollector { private Collection<StyleRange> positions; private String partition; private Map<String, IPresentationDamager> damagers; private Map<String, IPresentationRepairer> repairers; public PositionCollector(Collection<StyleRange> positions) { this.positions = positions; } public IPresentationRepairer getRepairer(String contentType) { if (repairers == null) { return null; } return repairers.get(contentType); } public void setDamager(IPresentationDamager damager, String contentType) { if (damagers == null) { damagers = new HashMap<String, IPresentationDamager>(); } if (damager == null) { damagers.remove(contentType); } else { damagers.put(contentType, damager); } } public void setDocumentPartitioning(String partitioning) { partition = partitioning; } public void setRepairer(IPresentationRepairer repairer, String contentType) { if (repairers == null) { repairers = new HashMap<String, IPresentationRepairer>(); } if (repairer == null) { repairers.remove(contentType); } else { repairers.put(contentType, repairer); } } private TextPresentation createPresentation(IRegion damage, IDocument document) { try { if (repairers == null || repairers.isEmpty()) { TextPresentation presentation = new TextPresentation(damage, 100); presentation.setDefaultStyleRange(new StyleRange( damage.getOffset(), damage.getLength(), null, null)); return presentation; } TextPresentation presentation = new TextPresentation(damage, 1000); ITypedRegion[] partitioning = TextUtilities.computePartitioning( document, partition, damage.getOffset(), damage.getLength(), false); for (int i = 0; i < partitioning.length; i++) { ITypedRegion r = partitioning[i]; IPresentationRepairer repairer = getRepairer(r.getType()); if (repairer != null) { repairer.createPresentation(presentation, r); } } return presentation; } catch (BadLocationException x) { return null; } } private void processRegion(IRegion damage, IDocument document) { setDocumentToDamagers(document); setDocumentToRepairers(document); if (damage != null && damage.getLength() > 0) { TextPresentation p = createPresentation(damage, document); @SuppressWarnings("unchecked") List<StyleRange> styles = (List<StyleRange>) ReflectionUtils.getFieldObject(p, "fRanges"); for (StyleRange range : styles) { positions.add(range); } } } private void setDocumentToDamagers(IDocument document) { if (damagers != null) { Iterator<IPresentationDamager> e = damagers.values().iterator(); while (e.hasNext()) { IPresentationDamager damager = e.next(); damager.setDocument(document); } } } private void setDocumentToRepairers(IDocument document) { if (repairers != null) { Iterator<IPresentationRepairer> e = repairers.values().iterator(); while (e.hasNext()) { IPresentationRepairer repairer = e.next(); repairer.setDocument(document); } } } } private IPreferenceStore preferenceStore; private IColorManager colorManager; private DartCodeScanner codeScanner; private DartCommentScanner multilineCommentScanner; private DartCommentScanner singlelineCommentScanner; private SingleTokenDartScanner stringScanner; private DartMultilineStringScanner multilineStringScanner; private DartDocScanner docCommentScanner; public SyntacticHighlightingEngine(IColorManager colorManager, IPreferenceStore preferenceStore) { this.colorManager = colorManager; this.preferenceStore = preferenceStore; initializeScanners(); } public void analyze(IDocument document, IRegion region, Collection<StyleRange> positions) { PositionCollector collector = getPositionCollector(positions); collector.processRegion(region, document); } private PositionCollector getPositionCollector(Collection<StyleRange> positions) { PositionCollector reconciler = new PositionCollector(positions); reconciler.setDocumentPartitioning(DartPartitions.DART_PARTITIONING); DefaultDamagerRepairer dr = new DefaultDamagerRepairer(codeScanner); reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE); reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE); dr = new DefaultDamagerRepairer(docCommentScanner); reconciler.setDamager(new DartIndiscriminateDamager(), DartPartitions.DART_DOC); reconciler.setRepairer(dr, DartPartitions.DART_DOC); reconciler.setDamager(new DartIndiscriminateDamager(), DartPartitions.DART_SINGLE_LINE_DOC); reconciler.setRepairer(dr, DartPartitions.DART_SINGLE_LINE_DOC); dr = new DefaultDamagerRepairer(multilineCommentScanner); reconciler.setDamager(dr, DartPartitions.DART_MULTI_LINE_COMMENT); reconciler.setRepairer(dr, DartPartitions.DART_MULTI_LINE_COMMENT); dr = new DefaultDamagerRepairer(singlelineCommentScanner); reconciler.setDamager(dr, DartPartitions.DART_SINGLE_LINE_COMMENT); reconciler.setRepairer(dr, DartPartitions.DART_SINGLE_LINE_COMMENT); dr = new DefaultDamagerRepairer(stringScanner); reconciler.setDamager(dr, DartPartitions.DART_STRING); reconciler.setRepairer(dr, DartPartitions.DART_STRING); dr = new DefaultDamagerRepairer(multilineStringScanner); reconciler.setDamager(dr, DartPartitions.DART_MULTI_LINE_STRING); reconciler.setRepairer(dr, DartPartitions.DART_MULTI_LINE_STRING); return reconciler; } private void initializeScanners() { codeScanner = new DartCodeScanner(colorManager, preferenceStore); multilineCommentScanner = new DartCommentScanner( colorManager, preferenceStore, IDartColorConstants.JAVA_MULTI_LINE_COMMENT); singlelineCommentScanner = new DartCommentScanner( colorManager, preferenceStore, IDartColorConstants.JAVA_SINGLE_LINE_COMMENT); stringScanner = new SingleTokenDartScanner( colorManager, preferenceStore, IDartColorConstants.JAVA_STRING); multilineStringScanner = new DartMultilineStringScanner( colorManager, preferenceStore, IDartColorConstants.DART_MULTI_LINE_STRING); docCommentScanner = new DartDocScanner(colorManager, preferenceStore); } }