/****************************************************************************** * Copyright (C) 2015 Brainwy Software Ltda. * * 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: * Fabio Zadrozny <fabiofz@gmail.com> - initial API and implementation ******************************************************************************/ package org.python.pydev.editor; import java.lang.ref.WeakReference; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.rules.Token; import org.python.pydev.core.IGrammarVersionProvider; import org.python.pydev.core.MisconfigurationException; import org.python.pydev.core.docutils.PySelection; import org.python.pydev.ui.ColorAndStyleCache; public class PyBytesOrUnicodeScanner extends AbstractStringScanner { private WeakReference<PyPresentationReconciler> reconciler; public PyBytesOrUnicodeScanner(ColorAndStyleCache colorCache, IGrammarVersionProvider grammarVersionProvider, PyPresentationReconciler reconciler) { super(colorCache); this.setGrammarVersionProvider(grammarVersionProvider); this.reconciler = new WeakReference<>(reconciler); } @Override public void updateColorAndStyle() { if (defaultIsUnicode) { fStringReturnToken = new Token(colorCache.getUnicodeTextAttribute()); } else { fStringReturnToken = new Token(colorCache.getStringTextAttribute()); } fDocStringMarkupTextReturnToken = new Token(colorCache.getDocstringMarkupTextAttribute()); } private IGrammarVersionProvider grammarVersionProvider; private boolean hasFromFutureImportUnicode = false; private boolean defaultIsUnicode = false; private IDocument fDocument; private boolean setDefaultIsUnicode(boolean defaultIsUnicode) { if (defaultIsUnicode != this.defaultIsUnicode) { this.defaultIsUnicode = defaultIsUnicode; this.updateColorAndStyle(); PyPresentationReconciler r = this.reconciler.get(); if (r != null) { r.invalidateTextPresentation(); } return true; } return false; } public void setGrammarVersionProvider(IGrammarVersionProvider grammarVersionProvider) { if (grammarVersionProvider != null) { this.grammarVersionProvider = grammarVersionProvider; } } /** * Returns whether the setting changed. */ private void setFromFutureImportUnicode(boolean hasFromFutureImportUnicode) { if (this.hasFromFutureImportUnicode != hasFromFutureImportUnicode) { this.hasFromFutureImportUnicode = hasFromFutureImportUnicode; } } private boolean updateDefaultIsBytesOrUnicode() { if (hasFromFutureImportUnicode) { return setDefaultIsUnicode(true); } int grammarVersion = IGrammarVersionProvider.LATEST_GRAMMAR_VERSION; IGrammarVersionProvider g = grammarVersionProvider; if (g != null) { try { grammarVersion = g.getGrammarVersion(); } catch (MisconfigurationException e) { } } if (grammarVersion >= IGrammarVersionProvider.GRAMMAR_PYTHON_VERSION_3_0) { return setDefaultIsUnicode(true); } else { return setDefaultIsUnicode(false); } } private long last = 0; @Override public void setRange(IDocument document, int offset, int length) { if (this.fDocument != document) { this.fDocument = document; last = System.currentTimeMillis(); this.updateFutureUnicodeFromDocument(); } else { long curr = System.currentTimeMillis(); if (curr - last > 1000) { //Check at most one time/second last = curr; updateFutureUnicodeFromDocument(); } } super.setRange(document, offset, length); } private void updateFutureUnicodeFromDocument() { if (this.fDocument != null) { this.setFromFutureImportUnicode(PySelection.hasFromFutureImportUnicode(this.fDocument)); } //The grammar version or unicode literals could've changed... updateDefaultIsBytesOrUnicode(); } }