/******************************************************************************* * Copyright (c) 2006, 2016 Zend Corporation and IBM Corporation. * 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: * Zend and IBM - Initial implementation *******************************************************************************/ package org.eclipse.php.internal.ui.editor.highlighter; import java.util.Collection; import java.util.HashMap; import java.util.Map; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.ITypedRegion; import org.eclipse.jface.text.TextAttribute; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.php.internal.core.documentModel.parser.PHPRegionContext; import org.eclipse.php.internal.core.documentModel.parser.regions.IPHPScriptRegion; import org.eclipse.php.internal.core.documentModel.parser.regions.PHPRegionTypes; import org.eclipse.php.internal.ui.Logger; import org.eclipse.php.internal.ui.preferences.PreferenceConstants; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; 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.core.internal.provisional.text.ITextRegionCollection; import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList; import org.eclipse.wst.sse.core.internal.util.Debug; import org.eclipse.wst.sse.ui.internal.preferences.ui.ColorHelper; import org.eclipse.wst.sse.ui.internal.provisional.style.AbstractLineStyleProvider; import org.eclipse.wst.sse.ui.internal.provisional.style.LineStyleProvider; import org.eclipse.wst.sse.ui.internal.util.EditorUtility; /** * Coloring mechanism for PHP partitions */ public class LineStyleProviderForPHP extends AbstractLineStyleProvider implements LineStyleProvider { private IPreferenceStore fColorPreferences; /** Contains region to style mapping */ protected static final Map<String, String> fColorTypes = new HashMap<>(); // String // (token // type), // String // (color) static { // Normal text: fColorTypes.put(PHPRegionTypes.PHP_LABEL, PreferenceConstants.EDITOR_NORMAL_COLOR); fColorTypes.put(PHPRegionTypes.PHP_TOKEN, PreferenceConstants.EDITOR_NORMAL_COLOR); fColorTypes.put(PHPRegionTypes.PHP_SEMICOLON, PreferenceConstants.EDITOR_NORMAL_COLOR); fColorTypes.put(PHPRegionTypes.PHP_OPERATOR, PreferenceConstants.EDITOR_NORMAL_COLOR); // Boundary Markers fColorTypes.put(PHPRegionTypes.PHP_OPENTAG, PreferenceConstants.EDITOR_BOUNDARYMARKER_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CLOSETAG, PreferenceConstants.EDITOR_BOUNDARYMARKER_COLOR); // Keywords fColorTypes.put(PHPRegionTypes.PHP_LOGICAL_AND, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ARRAY, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_STRING, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FLOAT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_BOOL, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_VOID, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_AS, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_BREAK, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CASE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CATCH, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FINALLY, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CLASS, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CONTINUE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_GOTO, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_DECLARE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_DEFAULT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_DO, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ECHO, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ELSE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ELSEIF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_EMPTY, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDDECLARE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDFOR, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDFOREACH, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDIF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDSWITCH, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_EVAL, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_EXIT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_EXTENDS, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FOR, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FOREACH, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FUNCTION, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_IF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_HALT_COMPILER, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INCLUDE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INCLUDE_ONCE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_GLOBAL, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_LIST, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_NEW, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_NOT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_LOGICAL_OR, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_PRINT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_PUBLIC, PreferenceConstants.EDITOR_KEYWORD_PUBLIC_COLOR); fColorTypes.put(PHPRegionTypes.PHP_PRIVATE, PreferenceConstants.EDITOR_KEYWORD_PRIVATE_COLOR); fColorTypes.put(PHPRegionTypes.PHP_PROTECTED, PreferenceConstants.EDITOR_KEYWORD_PROTECTED_COLOR); fColorTypes.put(PHPRegionTypes.PHP_REQUIRE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_REQUIRE_ONCE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_RETURN, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_YIELD, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_STATIC, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_SWITCH, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_TRY, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_THROW, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_NAMESPACE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_USE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_VAR, PreferenceConstants.EDITOR_KEYWORD_PUBLIC_COLOR); fColorTypes.put(PHPRegionTypes.PHP_WHILE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_LOGICAL_XOR, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ABSTRACT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CLONE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FALSE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FINAL, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_DIE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_TRUE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INSTANCEOF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_UNSET, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_SELF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ISSET, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_PARENT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENDWHILE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_FROM, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_IMPLEMENTS, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INTERFACE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CONST, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_TRAIT, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_INSTEADOF, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_CALLABLE, PreferenceConstants.EDITOR_KEYWORD_COLOR); fColorTypes.put(PHPRegionTypes.PHP_KEYWORD, PreferenceConstants.EDITOR_KEYWORD_COLOR); // Variables fColorTypes.put(PHPRegionTypes.PHP_VARIABLE, PreferenceConstants.EDITOR_VARIABLE_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENCAPSED_VARIABLE, PreferenceConstants.EDITOR_VARIABLE_COLOR); fColorTypes.put(PHPRegionTypes.PHP_THIS, PreferenceConstants.EDITOR_VARIABLE_COLOR); // Strings fColorTypes.put(PHPRegionTypes.PHP_CONSTANT_ENCAPSED_STRING, PreferenceConstants.EDITOR_STRING_COLOR); fColorTypes.put(PHPRegionTypes.PHP_ENCAPSED_AND_WHITESPACE, PreferenceConstants.EDITOR_STRING_COLOR); // Comments fColorTypes.put(PHPRegionTypes.PHP_COMMENT, PreferenceConstants.EDITOR_COMMENT_COLOR); fColorTypes.put(PHPRegionTypes.PHP_COMMENT_START, PreferenceConstants.EDITOR_COMMENT_COLOR); fColorTypes.put(PHPRegionTypes.PHP_COMMENT_END, PreferenceConstants.EDITOR_COMMENT_COLOR); fColorTypes.put(PHPRegionTypes.PHP_LINE_COMMENT, PreferenceConstants.EDITOR_LINE_COMMENT_COLOR); // Numbers fColorTypes.put(PHPRegionTypes.PHP_NUMBER, PreferenceConstants.EDITOR_NUMBER_COLOR); // Heredocs/nowdocs fColorTypes.put(PHPRegionTypes.PHP_HEREDOC_START_TAG, PreferenceConstants.EDITOR_HEREDOC_COLOR); fColorTypes.put(PHPRegionTypes.PHP_HEREDOC_CLOSE_TAG, PreferenceConstants.EDITOR_HEREDOC_COLOR); fColorTypes.put(PHPRegionTypes.PHP_NOWDOC_START_TAG, PreferenceConstants.EDITOR_HEREDOC_COLOR); fColorTypes.put(PHPRegionTypes.PHP_NOWDOC_CLOSE_TAG, PreferenceConstants.EDITOR_HEREDOC_COLOR); // PHPDoc // fColorTypes.put(PHPRegionTypes.PHPDOC_TODO, // PreferenceConstants.EDITOR_TASK_COLOR); fColorTypes.put(PHPRegionTypes.PHPDOC_GENERIC_TAG, PreferenceConstants.EDITOR_PHPDOC_COLOR); fColorTypes.put(PHPRegionTypes.PHPDOC_COMMENT, PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR); fColorTypes.put(PHPRegionTypes.PHPDOC_COMMENT_START, PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR); fColorTypes.put(PHPRegionTypes.PHPDOC_COMMENT_END, PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR); // fColorTypes.put(PHPRegionTypes.TASK, // PreferenceConstants.EDITOR_TASK_COLOR); } /** * Returns the attribute for simple php regions (open/close) not PHP_CONTENT * regions * * @param region * @return the text attribute */ @Override protected TextAttribute getAttributeFor(ITextRegion region) { TextAttribute result = null; if (region != null) { final String type = region.getType(); if (type == PHPRegionContext.PHP_OPEN) { result = getAttributeFor(PHPRegionTypes.PHP_OPENTAG); } else if (type == PHPRegionContext.PHP_CLOSE) { result = getAttributeFor(PHPRegionTypes.PHP_CLOSETAG); } else { result = getAttributeFor(region.getType()); } } // return the default attributes if there is not highlight color for the // region if (result == null) { result = (TextAttribute) getTextAttributes().get(PreferenceConstants.EDITOR_NORMAL_COLOR); } return result; } /** * Look up the TextAttribute for the given region context. Might return null * for unusual text. * * @param type * @return */ protected TextAttribute getAttributeFor(String type) { return (TextAttribute) getTextAttributes().get(fColorTypes.get(type)); } /** * Looks up the colorKey in the preference store and adds the style * information to list of TextAttributes * * @param colorKey */ @Override protected void addTextAttribute(String colorKey) { if (getColorPreferences() != null) { String enableKey = PreferenceConstants.getEnabledPreferenceKey(colorKey); boolean enabled = getColorPreferences().getBoolean(enableKey); if (enabled) { String prefString = getColorPreferences().getString(colorKey); String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString); if (stylePrefs != null) { getTextAttributes().put(colorKey, createTextAttribute(stylePrefs)); } } else { addDefaultTextAttribute(colorKey); } } } protected void addDefaultTextAttribute(String colorKey) { if (getColorPreferences() != null) { String prefString = PreferenceConstants.EDITOR_NORMAL_DEFAULT_COLOR; String[] stylePrefs = ColorHelper.unpackStylePreferences(prefString); if (stylePrefs != null) { getTextAttributes().put(colorKey, createTextAttribute(stylePrefs)); } } } /* * Creates TextAttribute from the given style description array string */ protected TextAttribute createTextAttribute(String[] stylePrefs) { int fontModifier = SWT.NORMAL; if (Boolean.valueOf(stylePrefs[2]).booleanValue()) { // bold fontModifier |= SWT.BOLD; } if (Boolean.valueOf(stylePrefs[3]).booleanValue()) { // italic fontModifier |= SWT.ITALIC; } if (Boolean.valueOf(stylePrefs[4]).booleanValue()) { // strikethrough fontModifier |= TextAttribute.STRIKETHROUGH; } if (Boolean.valueOf(stylePrefs[5]).booleanValue()) { // underline fontModifier |= TextAttribute.UNDERLINE; } return new TextAttribute(EditorUtility.getColor(ColorHelper.toRGB(stylePrefs[0])), EditorUtility.getColor(ColorHelper.toRGB(stylePrefs[1])), fontModifier); } public TextAttribute getTextAttributeForColor(String colorKey) { return (TextAttribute) getTextAttributes().get(colorKey); } /** * this version does "trim" regions to match request */ protected StyleRange createStyleRange(ITextRegionCollection flatNode, ITextRegion region, TextAttribute attr, int startOffset, int length) { int start = flatNode.getStartOffset(region); if (start < startOffset) start = startOffset; int maxOffset = startOffset + length; int end = flatNode.getEndOffset(region); // use get length directly // instead of end-start? if (end > maxOffset) end = maxOffset; StyleRange result = new StyleRange(start, end - start, attr.getForeground(), attr.getBackground(), attr.getStyle()); if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) { result.underline = true; result.fontStyle &= ~TextAttribute.UNDERLINE; } if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) { result.strikeout = true; result.fontStyle &= ~TextAttribute.STRIKETHROUGH; } return result; } @Override public boolean prepareRegions(ITypedRegion typedRegion, int lineRequestStart, int lineRequestLength, Collection holdResults) { final int partitionStartOffset = typedRegion.getOffset(); final int partitionLength = typedRegion.getLength(); IStructuredDocumentRegion structuredDocumentRegion = getDocument() .getRegionAtCharacterOffset(partitionStartOffset); final boolean prepareTextRegions = prepareTextRegions(structuredDocumentRegion, partitionStartOffset, partitionLength, holdResults); return prepareTextRegions; } public IStructuredDocumentRegion getDamagedRegion(ITypedRegion typedRegion) { final int partitionStartOffset = typedRegion.getOffset(); return getDocument().getRegionAtCharacterOffset(partitionStartOffset); } /** * @param blockedRegion * @param partitionStartOffset * @param partitionLength * @param holdResults * @return */ public boolean prepareTextRegion(ITextRegionCollection blockedRegion, int partitionStartOffset, int partitionLength, Collection<StyleRange> holdResults) { if (blockedRegion == null) { return false; } assert blockedRegion.getLength() > 0 && partitionStartOffset >= 0 && partitionLength >= 0 && holdResults != null; if (partitionLength == 0) { return true; } boolean handled = false; final int partitionEndOffset = partitionStartOffset + partitionLength; ITextRegion region = null; ITextRegionList regions = blockedRegion.getRegions(); int nRegions = regions.size(); StyleRange styleRange = null; TextAttribute previousAttr = null; TextAttribute attr = null; int previousEndOffset = -1; for (int i = 0; i < nRegions; i++) { region = regions.get(i); final int startOffset = blockedRegion.getStartOffset(region); if (startOffset >= partitionEndOffset) break; if (blockedRegion.getEndOffset(region) <= partitionStartOffset) continue; if (region instanceof ITextRegionCollection) { handled = prepareTextRegion((ITextRegionCollection) region, partitionStartOffset, partitionLength, holdResults); previousAttr = null; styleRange = null; previousEndOffset = -1; } else { if (region.getType() == PHPRegionContext.PHP_CONTENT) { handled = preparePHPRegions(holdResults, (IPHPScriptRegion) region, startOffset, partitionStartOffset, partitionLength); previousAttr = null; styleRange = null; previousEndOffset = -1; } else { attr = getAttributeFor(region); if (attr != null) { handled = true; // if this region's attr is the same as previous one, // then just adjust the previous style range // instead of creating a new instance of one // note: to use 'equals' in this case is important, // since sometimes different instances of attributes are // associated with a region, even if the attribute has // the same values. // TODO: this needs to be improved to handle readonly // regions correctly if (styleRange != null && previousAttr != null && previousAttr.equals(attr) && previousEndOffset == startOffset) { // extends the prev styleRange with the current // region length styleRange.length += region.getLength(); if (styleRange.start + styleRange.length > partitionEndOffset) { styleRange.length -= styleRange.start + styleRange.length - partitionEndOffset; } } else { styleRange = createStyleRange(blockedRegion, region, attr, partitionStartOffset, partitionLength); holdResults.add(styleRange); } previousAttr = attr; previousEndOffset = blockedRegion.getEndOffset(region); } else { previousAttr = null; styleRange = null; previousEndOffset = -1; } } } } return handled; } public boolean prepareTextRegions(IStructuredDocumentRegion structuredDocumentRegion, int partitionStartOffset, int partitionLength, Collection<StyleRange> holdResults) { if (structuredDocumentRegion == null) { return false; } assert structuredDocumentRegion.getLength() > 0 && partitionStartOffset >= 0 && partitionLength >= 0 && holdResults != null; if (partitionLength == 0) { return true; } boolean handled = false; final int partitionEndOffset = partitionStartOffset + partitionLength; while (structuredDocumentRegion != null && structuredDocumentRegion.getStartOffset() < partitionEndOffset) { ITextRegion region = null; ITextRegionList regions = structuredDocumentRegion.getRegions(); int nRegions = regions.size(); StyleRange styleRange = null; TextAttribute previousAttr = null; TextAttribute attr = null; int previousEndOffset = -1; for (int i = 0; i < nRegions; i++) { region = regions.get(i); final int startOffset = structuredDocumentRegion.getStartOffset(region); if (startOffset >= partitionEndOffset) break; if (structuredDocumentRegion.getEndOffset(region) <= partitionStartOffset) continue; if (region instanceof ITextRegionCollection) { handled = prepareTextRegion((ITextRegionCollection) region, partitionStartOffset, partitionLength, holdResults); previousAttr = null; styleRange = null; previousEndOffset = -1; } else { if (region.getType() == PHPRegionContext.PHP_CONTENT) { handled = preparePHPRegions(holdResults, (IPHPScriptRegion) region, startOffset, partitionStartOffset, partitionLength); previousAttr = null; styleRange = null; previousEndOffset = -1; } else { attr = getAttributeFor(region); if (attr != null) { handled = true; // if this region's attr is the same as previous // one, then just adjust the previous style range // instead of creating a new instance of one // note: to use 'equals' in this case is important, // since sometimes different instances of attributes // are associated with a region, even if the // attribute has the same values. // TODO: this needs to be improved to handle // readonly regions correctly if (styleRange != null && previousAttr != null && previousAttr.equals(attr) && previousEndOffset == startOffset) { // extends the prev styleRange with the current // region length styleRange.length += region.getLength(); if (styleRange.start + styleRange.length > partitionEndOffset) { styleRange.length -= styleRange.start + styleRange.length - partitionEndOffset; } } else { styleRange = createStyleRange(structuredDocumentRegion, region, attr, partitionStartOffset, partitionLength); holdResults.add(styleRange); } previousAttr = attr; previousEndOffset = structuredDocumentRegion.getEndOffset(region); } else { previousAttr = null; styleRange = null; previousEndOffset = -1; } } } if (Debug.syntaxHighlighting) { if (!handled) { System.out.println("not handled in prepareRegions"); //$NON-NLS-1$ } } } structuredDocumentRegion = structuredDocumentRegion.getNext(); } return handled; } /** * Prepares php regions for the line highlighter * * @param holdResults * - results * @param region * - php region * @param regionStart * @param partitionStartOffset * @param partitionLength */ private boolean preparePHPRegions(Collection<StyleRange> holdResults, IPHPScriptRegion region, int regionStart, int partitionStartOffset, int partitionLength) { assert holdResults != null && region != null && region.getType() == PHPRegionContext.PHP_CONTENT && region.getLength() > 0 && regionStart >= 0 && partitionStartOffset >= 0 && partitionLength > 0; ITextRegion[] phpTokens; StyleRange styleRange = null; TextAttribute previousAttr = null; TextAttribute attr = null; ITextRegion prevElement = null; try { if (!region.isFullReparsed() && (regionStart == partitionStartOffset)) { phpTokens = region.getUpdatedPHPTokens(); int from = region.getUpdatedTokensStart(); partitionStartOffset = from + regionStart; partitionLength = region.getUpdatedTokensLength(); assert (phpTokens.length > 0 && partitionStartOffset >= 0 && partitionLength > 0) || (phpTokens.length == 0 && partitionStartOffset >= 0 && partitionLength == 0); } else { // compute interval intersection between region and partition int from = Math.max(0, partitionStartOffset - regionStart); int length = Math.min(regionStart + region.getLength(), partitionStartOffset + partitionLength) - Math.max(regionStart, partitionStartOffset); if (length == 0) { // empty region and partition intersection, there's nothing // to do (happens when partitionLength is = 0, so we should // never land here) return true; } // if length < 0 (i.e. when partitionLength < 0), we'll throw a // BadLocationException phpTokens = region.getPHPTokens(from, length); } for (int i = 0; i < phpTokens.length; i++) { ITextRegion element = phpTokens[i]; attr = getAttributeFor(element); // Check that the elements are different, otherwise the // coloring is not valid if (prevElement == element) { continue; } if (styleRange != null && previousAttr != null && previousAttr.equals(attr) && prevElement != null && prevElement.getStart() + prevElement.getLength() == element.getStart()) { // extends the prev styleRange with the current element // length styleRange.length += element.getLength(); if (styleRange.start + styleRange.length > partitionStartOffset + partitionLength) { styleRange.length -= styleRange.start + styleRange.length - (partitionStartOffset + partitionLength); } } else { // create new styleRange int styleStart = regionStart + element.getStart(); int styleLength = element.getLength(); int blankStart = regionStart + element.getTextEnd(); int blankLength = element.getEnd() - element.getTextEnd(); assert styleStart + styleLength == blankStart + blankLength; if (styleStart >= partitionStartOffset + partitionLength) { // if the range starts after the requested partition, // stop now break; } else if (styleStart + styleLength <= partitionStartOffset) { // if the range ends before the requested // starting position, ignore it continue; } else if (styleStart < partitionStartOffset) { // if the region starts before the requested // starting position, adjust the style start // position styleLength -= (partitionStartOffset - styleStart); styleStart = partitionStartOffset; if (blankStart < partitionStartOffset) { blankLength -= partitionStartOffset - blankStart; } } else if (styleStart + styleLength > partitionStartOffset + partitionLength) { // if the region ends after the requested end position, // making it shorter styleLength -= styleStart + styleLength - (partitionStartOffset + partitionLength); if (blankStart < partitionStartOffset + partitionLength) { blankLength = partitionStartOffset + partitionLength - blankStart; } else { blankLength = 0; } } if (attr.getBackground() != null && element.getTextEnd() != element.getEnd()) { // in case of background color make sure the // highlighting will not paint the whitespaces styleRange = new StyleRange(styleStart, styleLength - blankLength, attr.getForeground(), attr.getBackground(), attr.getStyle()); if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) { styleRange.underline = true; styleRange.fontStyle &= ~TextAttribute.UNDERLINE; } if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) { styleRange.strikeout = true; styleRange.fontStyle &= ~TextAttribute.STRIKETHROUGH; } holdResults.add(styleRange); previousAttr = attr; if (blankLength > 0) { // apply style to the whitespace (important for // the refresh of the specific range styleRange = new StyleRange(styleStart + styleLength - blankLength, blankLength, attr.getForeground(), null, attr.getStyle()); holdResults.add(styleRange); previousAttr = null; } } else { styleRange = new StyleRange(styleStart, styleLength, attr.getForeground(), attr.getBackground(), attr.getStyle()); if ((attr.getStyle() & TextAttribute.UNDERLINE) != 0) { styleRange.underline = true; styleRange.fontStyle &= ~TextAttribute.UNDERLINE; } if ((attr.getStyle() & TextAttribute.STRIKETHROUGH) != 0) { styleRange.strikeout = true; styleRange.fontStyle &= ~TextAttribute.STRIKETHROUGH; } holdResults.add(styleRange); previousAttr = attr; } } prevElement = element; } return true; } catch (BadLocationException e) { Logger.logException(e); return false; } } /* * Returns hash of color attributes */ public Map<String, String> getColorTypesMap() { return fColorTypes; } @Override public void loadColors() { addTextAttribute(PreferenceConstants.EDITOR_NORMAL_COLOR); addTextAttribute(PreferenceConstants.EDITOR_BOUNDARYMARKER_COLOR); addTextAttribute(PreferenceConstants.EDITOR_KEYWORD_COLOR); addTextAttribute(PreferenceConstants.EDITOR_VARIABLE_COLOR); addTextAttribute(PreferenceConstants.EDITOR_STRING_COLOR); addTextAttribute(PreferenceConstants.EDITOR_COMMENT_COLOR); addTextAttribute(PreferenceConstants.EDITOR_LINE_COMMENT_COLOR); addTextAttribute(PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR); addTextAttribute(PreferenceConstants.EDITOR_PHPDOC_COLOR); addTextAttribute(PreferenceConstants.EDITOR_NUMBER_COLOR); addTextAttribute(PreferenceConstants.EDITOR_HEREDOC_COLOR); // addTextAttribute(PreferenceConstants.EDITOR_TASK_COLOR); addTextAttribute(PreferenceConstants.EDITOR_KEYWORD_PRIVATE_COLOR); addTextAttribute(PreferenceConstants.EDITOR_KEYWORD_PUBLIC_COLOR); addTextAttribute(PreferenceConstants.EDITOR_KEYWORD_PROTECTED_COLOR); } protected void clearColors() { getTextAttributes().clear(); } public void setColorPreferences(IPreferenceStore preferenceStore) { fColorPreferences = preferenceStore; } @Override public IPreferenceStore getColorPreferences() { if (fColorPreferences != null) { return fColorPreferences; } return PreferenceConstants.getPreferenceStore(); } /* * Handle preference changes */ @Override protected void handlePropertyChange(PropertyChangeEvent event) { if (event != null) { String prefKey = event.getProperty(); if (PreferenceConstants.EDITOR_NORMAL_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_BOUNDARYMARKER_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_KEYWORD_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_VARIABLE_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_STRING_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_COMMENT_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_LINE_COMMENT_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_PHPDOC_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_NUMBER_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_HEREDOC_COLOR.equals(prefKey) // || PreferenceConstants.EDITOR_TASK_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_KEYWORD_PRIVATE_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_KEYWORD_PROTECTED_COLOR.equals(prefKey) || PreferenceConstants.EDITOR_KEYWORD_PUBLIC_COLOR.equals(prefKey)) { addTextAttribute(prefKey); } else if (PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_NORMAL_COLOR).equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_BOUNDARYMARKER_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_KEYWORD_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_VARIABLE_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_STRING_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_COMMENT_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_LINE_COMMENT_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_PHPDOC_COMMENT_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_PHPDOC_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_NUMBER_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_HEREDOC_COLOR) .equals(prefKey) // || // PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_TASK_COLOR) // .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_KEYWORD_PRIVATE_COLOR) .equals(prefKey) || PreferenceConstants .getEnabledPreferenceKey(PreferenceConstants.EDITOR_KEYWORD_PROTECTED_COLOR) .equals(prefKey) || PreferenceConstants.getEnabledPreferenceKey(PreferenceConstants.EDITOR_KEYWORD_PUBLIC_COLOR) .equals(prefKey)) { boolean enabled = getColorPreferences().getBoolean(prefKey); prefKey = prefKey.split("\\.")[1]; //$NON-NLS-1$ if (enabled) { addTextAttribute(prefKey); } else { addDefaultTextAttribute(prefKey); } } } else { loadColors(); } if (fRecHighlighter != null) { fRecHighlighter.refreshDisplay(); } } }