mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-07 01:36:01 +02:00
Semantic Highlighting (140335)
This commit is contained in:
parent
3a46db2f34
commit
487bac0828
32 changed files with 8604 additions and 300 deletions
|
@ -0,0 +1,120 @@
|
||||||
|
#define SIMPLE_MACRO
|
||||||
|
#define FUNCTION_MACRO(arg) globalFunc(arg)
|
||||||
|
|
||||||
|
enum Enumeration {
|
||||||
|
enumerator
|
||||||
|
};
|
||||||
|
|
||||||
|
const int globalConstant = 0;
|
||||||
|
int globalVariable = 0;
|
||||||
|
static int globalStaticVariable;
|
||||||
|
|
||||||
|
void globalFunc(int a);
|
||||||
|
static void globalStaticFunc() {
|
||||||
|
};
|
||||||
|
|
||||||
|
class Base1 {};
|
||||||
|
class Base2 {};
|
||||||
|
|
||||||
|
class ClassContainer : Base1, Base2 {
|
||||||
|
friend void friendFunc();
|
||||||
|
friend class FriendClass;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static int staticPubField;
|
||||||
|
const int constPubField;
|
||||||
|
const static int constStaticPubField;
|
||||||
|
int pubField;
|
||||||
|
|
||||||
|
static int staticPubMethod(int arg) {
|
||||||
|
FUNCTION_MACRO(arg);
|
||||||
|
globalFunc(arg);
|
||||||
|
}
|
||||||
|
int pubMethod();
|
||||||
|
|
||||||
|
enum pubEnumeration {pubEnumerator};
|
||||||
|
class pubClass{};
|
||||||
|
class pubStruct{};
|
||||||
|
class pubUnion{};
|
||||||
|
typedef pubClass pubTypedef;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static const int constStaticProtField = 12;
|
||||||
|
static int staticProtField;
|
||||||
|
const int constProtField;
|
||||||
|
int protField;
|
||||||
|
|
||||||
|
static int staticProtMethod();
|
||||||
|
int protMethod();
|
||||||
|
|
||||||
|
enum protEnumeration {protEnumerator};
|
||||||
|
class protClass{};
|
||||||
|
class protStruct{};
|
||||||
|
class protUnion{};
|
||||||
|
typedef protClass protTypedef;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const int constStaticPrivField = 12;
|
||||||
|
static int staticPrivField;
|
||||||
|
const int constPrivField;
|
||||||
|
int privField;
|
||||||
|
|
||||||
|
static int staticPrivMethod();
|
||||||
|
int privMethod();
|
||||||
|
|
||||||
|
enum privEnumeration {privEnumerator};
|
||||||
|
class privClass{};
|
||||||
|
class privStruct{};
|
||||||
|
class privUnion{};
|
||||||
|
typedef privClass privTypedef;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<T1,T2> class TemplateClass {
|
||||||
|
T1 tArg1;
|
||||||
|
T2 tArg2;
|
||||||
|
TemplateClass(T1 arg1, T2 arg2) {
|
||||||
|
tArg1 = arg1;
|
||||||
|
tArg2 = arg2;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<T1> class PartialInstantiatedClass : TemplateClass<T1,Base1> {};
|
||||||
|
|
||||||
|
|
||||||
|
struct CppStruct {
|
||||||
|
int structField;
|
||||||
|
};
|
||||||
|
|
||||||
|
union CppUnion {
|
||||||
|
int unionField;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef CppUnion TUnion;
|
||||||
|
|
||||||
|
namespace ns {
|
||||||
|
int namespaceField = 0;
|
||||||
|
int namespaceFunc() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassContainer::protMethod() {
|
||||||
|
return protField;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassContainer::pubMethod() {
|
||||||
|
int localVar;
|
||||||
|
return pubField;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ClassContainer::staticPrivMethod() {
|
||||||
|
CppStruct st= new CppStruct();
|
||||||
|
st.structField= 1;
|
||||||
|
CppUnion un= new CppUnion();
|
||||||
|
un.unionField= 2;
|
||||||
|
staticPubMethod(staticPrivField);
|
||||||
|
label:
|
||||||
|
FUNCTION_MACRO(0);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2005 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import junit.extensions.TestSetup;
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
import org.eclipse.jface.text.BadPositionCategoryException;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.Position;
|
||||||
|
import org.eclipse.jface.text.source.SourceViewer;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.CEditor;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlighting;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingManager;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingPresenter;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Derived from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class AbstractSemanticHighlightingTest extends TestCase {
|
||||||
|
|
||||||
|
protected static class SemanticHighlightingTestSetup extends TestSetup {
|
||||||
|
|
||||||
|
private ICProject fCProject;
|
||||||
|
private final String fTestFilename;
|
||||||
|
|
||||||
|
public SemanticHighlightingTestSetup(Test test, String testFilename) {
|
||||||
|
super(test);
|
||||||
|
fTestFilename= testFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
fCProject= EditorTestHelper.createCProject(PROJECT, LINKED_FOLDER);
|
||||||
|
|
||||||
|
disableAllSemanticHighlightings();
|
||||||
|
|
||||||
|
fEditor= (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(fTestFilename), true);
|
||||||
|
fSourceViewer= EditorTestHelper.getSourceViewer(fEditor);
|
||||||
|
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTestFilename() {
|
||||||
|
return "/SHTest/src/SHTest.cpp";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void tearDown () throws Exception {
|
||||||
|
EditorTestHelper.closeEditor(fEditor);
|
||||||
|
|
||||||
|
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
|
||||||
|
SemanticHighlighting[] semanticHighlightings= SemanticHighlightings.getSemanticHighlightings();
|
||||||
|
for (int i= 0, n= semanticHighlightings.length; i < n; i++) {
|
||||||
|
String enabledPreferenceKey= SemanticHighlightings.getEnabledPreferenceKey(semanticHighlightings[i]);
|
||||||
|
if (!store.isDefault(enabledPreferenceKey))
|
||||||
|
store.setToDefault(enabledPreferenceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fCProject != null)
|
||||||
|
CProjectHelper.delete(fCProject);
|
||||||
|
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String LINKED_FOLDER= "resources/semanticHighlighting";
|
||||||
|
|
||||||
|
public static final String PROJECT= "SHTest";
|
||||||
|
|
||||||
|
private static CEditor fEditor;
|
||||||
|
|
||||||
|
private static SourceViewer fSourceViewer;
|
||||||
|
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
disableAllSemanticHighlightings();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void assertEqualPositions(Position[] expected, Position[] actual) {
|
||||||
|
assertEquals(expected.length, actual.length);
|
||||||
|
for (int i= 0, n= expected.length; i < n; i++) {
|
||||||
|
assertEquals(expected[i].isDeleted(), actual[i].isDeleted());
|
||||||
|
assertEquals(expected[i].getOffset(), actual[i].getOffset());
|
||||||
|
assertEquals(expected[i].getLength(), actual[i].getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Position createPosition(int line, int column, int length) throws BadLocationException {
|
||||||
|
IDocument document= fSourceViewer.getDocument();
|
||||||
|
return new Position(document.getLineOffset(line) + column, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
String toString(Position[] positions) throws BadLocationException {
|
||||||
|
StringBuffer buf= new StringBuffer();
|
||||||
|
IDocument document= fSourceViewer.getDocument();
|
||||||
|
buf.append("Position[] expected= new Position[] {\n");
|
||||||
|
for (int i= 0, n= positions.length; i < n; i++) {
|
||||||
|
Position position= positions[i];
|
||||||
|
int line= document.getLineOfOffset(position.getOffset());
|
||||||
|
int column= position.getOffset() - document.getLineOffset(line);
|
||||||
|
buf.append("\tcreatePosition(" + line + ", " + column + ", " + position.getLength() + "),\n");
|
||||||
|
}
|
||||||
|
buf.append("};\n");
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Position[] getSemanticHighlightingPositions() throws BadPositionCategoryException {
|
||||||
|
SemanticHighlightingManager manager= (SemanticHighlightingManager) new Accessor(fEditor, CEditor.class).get("fSemanticManager");
|
||||||
|
SemanticHighlightingPresenter presenter= (SemanticHighlightingPresenter) new Accessor(manager, manager.getClass()).get("fPresenter");
|
||||||
|
String positionCategory= (String) new Accessor(presenter, presenter.getClass()).invoke("getPositionCategory", new Object[0]);
|
||||||
|
IDocument document= fSourceViewer.getDocument();
|
||||||
|
return document.getPositions(positionCategory);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setUpSemanticHighlighting(String semanticHighlighting) {
|
||||||
|
enableSemanticHighlighting(semanticHighlighting);
|
||||||
|
EditorTestHelper.forceReconcile(fSourceViewer);
|
||||||
|
assertTrue(EditorTestHelper.joinReconciler(fSourceViewer, 0, 10000, 100));
|
||||||
|
EditorTestHelper.runEventQueue(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void enableSemanticHighlighting(String preferenceKey) {
|
||||||
|
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
store.setValue(getEnabledPreferenceKey(preferenceKey), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getEnabledPreferenceKey(String preferenceKey) {
|
||||||
|
return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + preferenceKey + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED_SUFFIX;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void disableAllSemanticHighlightings() {
|
||||||
|
IPreferenceStore store= CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
store.setValue(PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED, true);
|
||||||
|
SemanticHighlighting[] semanticHilightings= SemanticHighlightings.getSemanticHighlightings();
|
||||||
|
for (int i= 0, n= semanticHilightings.length; i < n; i++) {
|
||||||
|
SemanticHighlighting semanticHilighting= semanticHilightings[i];
|
||||||
|
if (store.getBoolean(SemanticHighlightings.getEnabledPreferenceKey(semanticHilighting)))
|
||||||
|
store.setValue(SemanticHighlightings.getEnabledPreferenceKey(semanticHilighting), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,328 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper class for accessing classes and members which cannot
|
||||||
|
* be accessed using standard Java access control like private
|
||||||
|
* or package visible elements.
|
||||||
|
*
|
||||||
|
* <p>Copied from JDT.</p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class Accessor extends Assert {
|
||||||
|
|
||||||
|
/** The class to access. */
|
||||||
|
private Class fClass;
|
||||||
|
/** The instance to access. */
|
||||||
|
private Object fInstance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an accessor for the given <code>instance</code> and
|
||||||
|
* <code>class</code>. Only non-inherited members that particular
|
||||||
|
* <code>class</code> can be accessed.
|
||||||
|
*
|
||||||
|
* @param instance the instance
|
||||||
|
* @param clazz the class
|
||||||
|
*/
|
||||||
|
public Accessor(Object instance, Class clazz) {
|
||||||
|
assertNotNull(instance);
|
||||||
|
assertNotNull(clazz);
|
||||||
|
fInstance= instance;
|
||||||
|
fClass= clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an accessor for the given <code>instance</code> and
|
||||||
|
* <code>class</code>. Only non-inherited members that particular
|
||||||
|
* <code>class</code> can be accessed.
|
||||||
|
*
|
||||||
|
* @param instance the instance
|
||||||
|
* @param className the name of the class
|
||||||
|
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
|
||||||
|
*/
|
||||||
|
public Accessor(Object instance, String className, ClassLoader classLoader) {
|
||||||
|
assertNotNull(instance);
|
||||||
|
assertNotNull(className);
|
||||||
|
assertNotNull(classLoader);
|
||||||
|
fInstance= instance;
|
||||||
|
try {
|
||||||
|
fClass= Class.forName(className, true, classLoader);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
fail();
|
||||||
|
} catch (ExceptionInInitializerError e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an accessor for the given class.
|
||||||
|
* <p>
|
||||||
|
* In order to get the type information from the given
|
||||||
|
* arguments they must all be instanc eof Object. Use
|
||||||
|
* {@link #Accessor(String, ClassLoader, Class[], Object[])} if this
|
||||||
|
* is not the case.</p>
|
||||||
|
*
|
||||||
|
* @param className the name of the class
|
||||||
|
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
|
||||||
|
* @param constructorArgs the constructor arguments which must all be instance of Object
|
||||||
|
*/
|
||||||
|
public Accessor(String className, ClassLoader classLoader, Object[] constructorArgs) {
|
||||||
|
this(className, classLoader, getTypes(constructorArgs), constructorArgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an accessor for the given class.
|
||||||
|
*
|
||||||
|
* @param className the name of the class
|
||||||
|
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
|
||||||
|
* @param constructorTypes the types of the constructor arguments
|
||||||
|
* @param constructorArgs the constructor arguments
|
||||||
|
*/
|
||||||
|
public Accessor(String className, ClassLoader classLoader, Class[] constructorTypes, Object[] constructorArgs) {
|
||||||
|
try {
|
||||||
|
fClass= Class.forName(className, true, classLoader);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
fail();
|
||||||
|
} catch (ExceptionInInitializerError e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
Constructor constructor= null;
|
||||||
|
try {
|
||||||
|
constructor= fClass.getDeclaredConstructor(constructorTypes);
|
||||||
|
} catch (SecurityException e2) {
|
||||||
|
fail();
|
||||||
|
} catch (NoSuchMethodException e2) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
assertNotNull(constructor);
|
||||||
|
constructor.setAccessible(true);
|
||||||
|
try {
|
||||||
|
fInstance= constructor.newInstance(constructorArgs);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
fail();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an accessor for the given class.
|
||||||
|
* <p>
|
||||||
|
* This constructor is used to access static stuff.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param className the name of the class
|
||||||
|
* @param classLoader the class loader to use i.e. <code>getClass().getClassLoader()</code>
|
||||||
|
*/
|
||||||
|
public Accessor(String className, ClassLoader classLoader) {
|
||||||
|
try {
|
||||||
|
fClass= Class.forName(className, true, classLoader);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
fail();
|
||||||
|
} catch (ExceptionInInitializerError e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the method with the given method name and arguments.
|
||||||
|
* <p>
|
||||||
|
* In order to get the type information from the given
|
||||||
|
* arguments all those arguments must be instance of Object. Use
|
||||||
|
* {@link #invoke(String, Class[], Object[])} if this
|
||||||
|
* is not the case.</p>
|
||||||
|
*
|
||||||
|
* @param methodName the method name
|
||||||
|
* @param arguments the method arguments which must all be instance of Object
|
||||||
|
* @return the method return value
|
||||||
|
*/
|
||||||
|
public Object invoke(String methodName, Object[] arguments) {
|
||||||
|
return invoke(methodName, getTypes(arguments), arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the method with the given method name and arguments.
|
||||||
|
*
|
||||||
|
* @param methodName the method name
|
||||||
|
* @param types the argument types
|
||||||
|
* @param arguments the method arguments
|
||||||
|
* @return the method return value
|
||||||
|
*/
|
||||||
|
public Object invoke(String methodName, Class[] types, Object[] arguments) {
|
||||||
|
Method method= null;
|
||||||
|
try {
|
||||||
|
method= fClass.getDeclaredMethod(methodName, types);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
fail();
|
||||||
|
} catch (NoSuchMethodException ex) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
assertNotNull(method);
|
||||||
|
method.setAccessible(true);
|
||||||
|
try {
|
||||||
|
return method.invoke(fInstance, arguments);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns the given value to the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @param value the value to assign to the field
|
||||||
|
*/
|
||||||
|
public void set(String fieldName, Object value) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
field.set(fInstance, value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns the given value to the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @param value the value to assign to the field
|
||||||
|
*/
|
||||||
|
public void set(String fieldName, boolean value) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
field.setBoolean(fInstance, value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assigns the given value to the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @param value the value to assign to the field
|
||||||
|
*/
|
||||||
|
public void set(String fieldName, int value) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
field.setInt(fInstance, value);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @return the value of the field
|
||||||
|
*/
|
||||||
|
public Object get(String fieldName) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
return field.get(fInstance);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
// Unreachable code
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @return the value of the field
|
||||||
|
*/
|
||||||
|
public boolean getBoolean(String fieldName) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
return field.getBoolean(fInstance);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
// Unreachable code
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the value of the field with the given name.
|
||||||
|
*
|
||||||
|
* @param fieldName the field name
|
||||||
|
* @return the value of the field
|
||||||
|
*/
|
||||||
|
public int getInt(String fieldName) {
|
||||||
|
Field field= getField(fieldName);
|
||||||
|
try {
|
||||||
|
return field.getInt(fInstance);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
fail();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
// Unreachable code
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Field getField(String fieldName) {
|
||||||
|
Field field= null;
|
||||||
|
try {
|
||||||
|
field= fClass.getDeclaredField(fieldName);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
fail();
|
||||||
|
} catch (NoSuchFieldException e) {
|
||||||
|
fail();
|
||||||
|
}
|
||||||
|
field.setAccessible(true);
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Class[] getTypes(Object[] objects) {
|
||||||
|
if (objects == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int length= objects.length;
|
||||||
|
Class[] classes= new Class[length];
|
||||||
|
for (int i= 0; i < length; i++) {
|
||||||
|
assertNotNull(objects[i]);
|
||||||
|
classes[i]= objects[i].getClass();
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,621 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the event loop of the given display until {@link #condition()} becomes
|
||||||
|
* <code>true</code> or no events have occurred for the supplied timeout.
|
||||||
|
* Between running the event loop, {@link Display#sleep()} is called.
|
||||||
|
* <p>
|
||||||
|
* There is a caveat: the given timeouts must be long enough that the calling
|
||||||
|
* thread can enter <code>Display.sleep()</code> before the timeout elapses,
|
||||||
|
* otherwise, the waiter may time out before <code>sleep</code> is called and
|
||||||
|
* the sleeping thread may never be waken up.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>Copied from org.eclipse.jdt.testplugin.util.</p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public abstract class DisplayHelper {
|
||||||
|
/**
|
||||||
|
* Creates a new instance.
|
||||||
|
*/
|
||||||
|
protected DisplayHelper() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Until {@link #condition()} becomes <code>true</code> or the timeout
|
||||||
|
* elapses, call {@link Display#sleep()} and run the event loop.
|
||||||
|
* <p>
|
||||||
|
* If <code>timeout < 0</code>, the event loop is never driven and
|
||||||
|
* only the condition is checked. If <code>timeout == 0</code>, the event
|
||||||
|
* loop is driven at most once, but <code>Display.sleep()</code> is never
|
||||||
|
* invoked.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
* @param timeout the timeout in milliseconds
|
||||||
|
* @return <code>true</code> if the condition became <code>true</code>,
|
||||||
|
* <code>false</code> if the timeout elapsed
|
||||||
|
*/
|
||||||
|
public final boolean waitForCondition(Display display, long timeout) {
|
||||||
|
// if the condition already holds, succeed
|
||||||
|
if (condition())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (timeout < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if driving the event loop once makes the condition hold, succeed
|
||||||
|
// without spawning a thread.
|
||||||
|
driveEventQueue(display);
|
||||||
|
if (condition())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// if the timeout is negative or zero, fail
|
||||||
|
if (timeout == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// repeatedly sleep until condition becomes true or timeout elapses
|
||||||
|
DisplayWaiter waiter= new DisplayWaiter(display);
|
||||||
|
DisplayWaiter.Timeout timeoutState= waiter.start(timeout);
|
||||||
|
boolean condition;
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
if (display.sleep())
|
||||||
|
driveEventQueue(display);
|
||||||
|
condition= condition();
|
||||||
|
} while (!condition && !timeoutState.hasTimedOut());
|
||||||
|
} finally {
|
||||||
|
waiter.stop();
|
||||||
|
}
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link Display#sleep()} and run the event loop until the given
|
||||||
|
* timeout has elapsed.
|
||||||
|
* <p>
|
||||||
|
* If <code>timeout < 0</code>, nothing happens. If
|
||||||
|
* <code>timeout == 0</code>, the event loop is driven exactly once, but
|
||||||
|
* <code>Display.sleep()</code> is never invoked.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
* @param millis the timeout in milliseconds
|
||||||
|
*/
|
||||||
|
public static void sleep(Display display, long millis) {
|
||||||
|
new DisplayHelper() {
|
||||||
|
public boolean condition() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}.waitForCondition(display, millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call {@link Display#sleep()} and run the event loop once if
|
||||||
|
* <code>sleep</code> returns before the timeout elapses. Returns
|
||||||
|
* <code>true</code> if any events were processed, <code>false</code> if
|
||||||
|
* not.
|
||||||
|
* <p>
|
||||||
|
* If <code>timeout < 0</code>, nothing happens and false is returned.
|
||||||
|
* If <code>timeout == 0</code>, the event loop is driven exactly once,
|
||||||
|
* but <code>Display.sleep()</code> is never invoked.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
* @param timeout the timeout in milliseconds
|
||||||
|
* @return <code>true</code> if any event was taken off the event queue,
|
||||||
|
* <code>false</code> if not
|
||||||
|
*/
|
||||||
|
public static boolean runEventLoop(Display display, long timeout) {
|
||||||
|
if (timeout < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (timeout == 0)
|
||||||
|
return driveEventQueue(display);
|
||||||
|
|
||||||
|
// repeatedly sleep until condition becomes true or timeout elapses
|
||||||
|
DisplayWaiter waiter= new DisplayWaiter(display);
|
||||||
|
DisplayWaiter.Timeout timeoutState= waiter.start(timeout);
|
||||||
|
boolean events= false;
|
||||||
|
if (display.sleep() && !timeoutState.hasTimedOut()) {
|
||||||
|
driveEventQueue(display);
|
||||||
|
events= true;
|
||||||
|
}
|
||||||
|
waiter.stop();
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The condition which has to be met in order for
|
||||||
|
* {@link #waitForCondition(Display, int)} to return before the timeout
|
||||||
|
* elapses.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the condition is met, <code>false</code>
|
||||||
|
* if the event loop should be driven some more
|
||||||
|
*/
|
||||||
|
protected abstract boolean condition();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the event loop on the given display.
|
||||||
|
*
|
||||||
|
* @param display the display
|
||||||
|
* @return if <code>display.readAndDispatch</code> returned
|
||||||
|
* <code>true</code> at least once
|
||||||
|
*/
|
||||||
|
private static boolean driveEventQueue(Display display) {
|
||||||
|
boolean events= false;
|
||||||
|
while (display.readAndDispatch()) {
|
||||||
|
events= true;
|
||||||
|
}
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Until {@link #condition()} becomes <code>true</code> or the timeout
|
||||||
|
* elapses, call {@link Display#sleep()} and run the event loop.
|
||||||
|
* <p>
|
||||||
|
* If <code>timeout < 0</code>, the event loop is never driven and
|
||||||
|
* only the condition is checked. If <code>timeout == 0</code>, the event
|
||||||
|
* loop is driven at most once, but <code>Display.sleep()</code> is never
|
||||||
|
* invoked.
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* The condition gets rechecked every <code>interval</code> milliseconds, even
|
||||||
|
* if no events were read from the queue.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
* @param timeout the timeout in milliseconds
|
||||||
|
* @param interval the interval to re-check the condition in milliseconds
|
||||||
|
* @return <code>true</code> if the condition became <code>true</code>,
|
||||||
|
* <code>false</code> if the timeout elapsed
|
||||||
|
*/
|
||||||
|
public final boolean waitForCondition(Display display, long timeout, long interval) {
|
||||||
|
// if the condition already holds, succeed
|
||||||
|
if (condition())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (timeout < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// if driving the event loop once makes the condition hold, succeed
|
||||||
|
// without spawning a thread.
|
||||||
|
driveEventQueue(display);
|
||||||
|
if (condition())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// if the timeout is negative or zero, fail
|
||||||
|
if (timeout == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// repeatedly sleep until condition becomes true or timeout elapses
|
||||||
|
DisplayWaiter waiter= new DisplayWaiter(display, true);
|
||||||
|
long currentTimeMillis= System.currentTimeMillis();
|
||||||
|
long finalTimeout= timeout + currentTimeMillis;
|
||||||
|
if (finalTimeout < currentTimeMillis)
|
||||||
|
finalTimeout= Long.MAX_VALUE;
|
||||||
|
boolean condition;
|
||||||
|
try {
|
||||||
|
do {
|
||||||
|
waiter.restart(interval);
|
||||||
|
if (display.sleep())
|
||||||
|
driveEventQueue(display);
|
||||||
|
condition= condition();
|
||||||
|
} while (!condition && finalTimeout > System.currentTimeMillis());
|
||||||
|
} finally {
|
||||||
|
waiter.stop();
|
||||||
|
}
|
||||||
|
return condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the thread that will wait for the timeout and wake up the display
|
||||||
|
* so it does not wait forever. The thread may be restarted after it was stopped
|
||||||
|
* or timed out.
|
||||||
|
*
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
final class DisplayWaiter {
|
||||||
|
/**
|
||||||
|
* Timeout state of a display waiter thread.
|
||||||
|
*/
|
||||||
|
public final class Timeout {
|
||||||
|
private boolean fTimeoutState= false;
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> if the timeout has been reached,
|
||||||
|
* <code>false</code> if not.
|
||||||
|
*
|
||||||
|
* @return <code>true</code> if the timeout has been reached,
|
||||||
|
* <code>false</code> if not
|
||||||
|
*/
|
||||||
|
public boolean hasTimedOut() {
|
||||||
|
synchronized (fMutex) {
|
||||||
|
return fTimeoutState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setTimedOut(boolean timedOut) {
|
||||||
|
fTimeoutState= timedOut;
|
||||||
|
}
|
||||||
|
Timeout(boolean initialState) {
|
||||||
|
fTimeoutState= initialState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// configuration
|
||||||
|
private final Display fDisplay;
|
||||||
|
private final Object fMutex= new Object();
|
||||||
|
private final boolean fKeepRunningOnTimeout;
|
||||||
|
|
||||||
|
/* State -- possible transitions:
|
||||||
|
*
|
||||||
|
* STOPPED -> RUNNING
|
||||||
|
* RUNNING -> STOPPED
|
||||||
|
* RUNNING -> IDLE
|
||||||
|
* IDLE -> RUNNING
|
||||||
|
* IDLE -> STOPPED
|
||||||
|
*/
|
||||||
|
private static final int RUNNING= 1 << 1;
|
||||||
|
private static final int STOPPED= 1 << 2;
|
||||||
|
private static final int IDLE= 1 << 3;
|
||||||
|
|
||||||
|
/** The current state. */
|
||||||
|
private int fState;
|
||||||
|
/** The time in milliseconds (see Date) that the timeout will occur. */
|
||||||
|
private long fNextTimeout;
|
||||||
|
/** The thread. */
|
||||||
|
private Thread fCurrentThread;
|
||||||
|
/** The timeout state of the current thread. */
|
||||||
|
private Timeout fCurrentTimeoutState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance on the given display and timeout.
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
*/
|
||||||
|
public DisplayWaiter(Display display) {
|
||||||
|
this(display, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance on the given display and timeout.
|
||||||
|
*
|
||||||
|
* @param display the display to run the event loop of
|
||||||
|
* @param keepRunning <code>true</code> if the thread should be kept
|
||||||
|
* running after timing out
|
||||||
|
*/
|
||||||
|
public DisplayWaiter(Display display, boolean keepRunning) {
|
||||||
|
Assert.assertNotNull(display);
|
||||||
|
fDisplay= display;
|
||||||
|
fState= STOPPED;
|
||||||
|
fKeepRunningOnTimeout= keepRunning;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the timeout thread if it is not currently running. Nothing happens
|
||||||
|
* if a thread is already running.
|
||||||
|
*
|
||||||
|
* @param delay the delay from now in milliseconds
|
||||||
|
* @return the timeout state which can be queried for its timed out status
|
||||||
|
*/
|
||||||
|
public Timeout start(long delay) {
|
||||||
|
Assert.assertTrue(delay > 0);
|
||||||
|
synchronized (fMutex) {
|
||||||
|
switch (fState) {
|
||||||
|
case STOPPED:
|
||||||
|
startThread();
|
||||||
|
setNextTimeout(delay);
|
||||||
|
break;
|
||||||
|
case IDLE:
|
||||||
|
unhold();
|
||||||
|
setNextTimeout(delay);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fCurrentTimeoutState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the next timeout to <em>current time</em> plus <code>delay</code>.
|
||||||
|
*
|
||||||
|
* @param delay the delay until the next timeout occurs in milliseconds from
|
||||||
|
* now
|
||||||
|
*/
|
||||||
|
private void setNextTimeout(long delay) {
|
||||||
|
long currentTimeMillis= System.currentTimeMillis();
|
||||||
|
long next= currentTimeMillis + delay;
|
||||||
|
if (next > currentTimeMillis)
|
||||||
|
fNextTimeout= next;
|
||||||
|
else
|
||||||
|
fNextTimeout= Long.MAX_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the thread if it is not currently running; resets the timeout if
|
||||||
|
* it is.
|
||||||
|
*
|
||||||
|
* @param delay the delay from now in milliseconds
|
||||||
|
* @return the timeout state which can be queried for its timed out status
|
||||||
|
*/
|
||||||
|
public Timeout restart(long delay) {
|
||||||
|
Assert.assertTrue(delay > 0);
|
||||||
|
synchronized (fMutex) {
|
||||||
|
switch (fState) {
|
||||||
|
case STOPPED:
|
||||||
|
startThread();
|
||||||
|
break;
|
||||||
|
case IDLE:
|
||||||
|
unhold();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
setNextTimeout(delay);
|
||||||
|
|
||||||
|
return fCurrentTimeoutState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the thread if it is running. If not, nothing happens. Another
|
||||||
|
* thread may be started by calling {@link #start(long)} or
|
||||||
|
* {@link #restart(long)}.
|
||||||
|
*/
|
||||||
|
public void stop() {
|
||||||
|
synchronized (fMutex) {
|
||||||
|
if (tryTransition(RUNNING | IDLE, STOPPED))
|
||||||
|
fMutex.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the reaper thread on hold but does not stop it. It may be restarted
|
||||||
|
* by calling {@link #start(long)} or {@link #restart(long)}.
|
||||||
|
*/
|
||||||
|
public void hold() {
|
||||||
|
synchronized (fMutex) {
|
||||||
|
// nothing to do if there is no thread
|
||||||
|
if (tryTransition(RUNNING, IDLE))
|
||||||
|
fMutex.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transition to <code>RUNNING</code> and clear the timed out flag. Assume
|
||||||
|
* current state is <code>IDLE</code>.
|
||||||
|
*/
|
||||||
|
private void unhold() {
|
||||||
|
checkedTransition(IDLE, RUNNING);
|
||||||
|
fCurrentTimeoutState= new Timeout(false);
|
||||||
|
fMutex.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start the thread. Assume the current state is <code>STOPPED</code>.
|
||||||
|
*/
|
||||||
|
private void startThread() {
|
||||||
|
checkedTransition(STOPPED, RUNNING);
|
||||||
|
fCurrentTimeoutState= new Timeout(false);
|
||||||
|
fCurrentThread= new Thread() {
|
||||||
|
/**
|
||||||
|
* Exception thrown when a thread notices that it has been stopped
|
||||||
|
* and a new thread has been started.
|
||||||
|
*/
|
||||||
|
final class ThreadChangedException extends Exception {
|
||||||
|
private static final long serialVersionUID= 1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see java.lang.Runnable#run()
|
||||||
|
*/
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
run2();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// ignore and end the thread - we never interrupt ourselves,
|
||||||
|
// so it must be an external entity that interrupted us
|
||||||
|
Logger.global.log(Level.FINE, "", e);
|
||||||
|
} catch (ThreadChangedException e) {
|
||||||
|
// the thread was stopped and restarted before we got out
|
||||||
|
// of a wait - we're no longer used
|
||||||
|
// we might have been notified instead of the current thread,
|
||||||
|
// so wake it up
|
||||||
|
Logger.global.log(Level.FINE, "", e);
|
||||||
|
synchronized (fMutex) {
|
||||||
|
fMutex.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the thread.
|
||||||
|
*
|
||||||
|
* @throws InterruptedException if the thread was interrupted
|
||||||
|
* @throws ThreadChangedException if the thread changed
|
||||||
|
*/
|
||||||
|
private void run2() throws InterruptedException, ThreadChangedException {
|
||||||
|
synchronized (fMutex) {
|
||||||
|
checkThread();
|
||||||
|
tryHold(); // wait / potential state change
|
||||||
|
assertStates(STOPPED | RUNNING);
|
||||||
|
|
||||||
|
while (isState(RUNNING)) {
|
||||||
|
waitForTimeout(); // wait / potential state change
|
||||||
|
|
||||||
|
if (isState(RUNNING))
|
||||||
|
timedOut(); // state change
|
||||||
|
assertStates(STOPPED | IDLE);
|
||||||
|
|
||||||
|
tryHold(); // wait / potential state change
|
||||||
|
assertStates(STOPPED | RUNNING);
|
||||||
|
}
|
||||||
|
assertStates(STOPPED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the current thread is this thread, throw an
|
||||||
|
* exception otherwise.
|
||||||
|
*
|
||||||
|
* @throws ThreadChangedException if the current thread changed
|
||||||
|
*/
|
||||||
|
private void checkThread() throws ThreadChangedException {
|
||||||
|
if (fCurrentThread != this)
|
||||||
|
throw new ThreadChangedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits until the next timeout occurs.
|
||||||
|
*
|
||||||
|
* @throws InterruptedException if the thread was interrupted
|
||||||
|
* @throws ThreadChangedException if the thread changed
|
||||||
|
*/
|
||||||
|
private void waitForTimeout() throws InterruptedException, ThreadChangedException {
|
||||||
|
long delta;
|
||||||
|
while (isState(RUNNING) && (delta = fNextTimeout - System.currentTimeMillis()) > 0) {
|
||||||
|
delta= Math.max(delta, 50); // wait at least 50ms in order to avoid timing out before the display is going to sleep
|
||||||
|
Logger.global.finest("sleeping for " + delta + "ms");
|
||||||
|
fMutex.wait(delta);
|
||||||
|
checkThread();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the timed out flag and wakes up the display. Transitions to
|
||||||
|
* <code>IDLE</code> (if in keep-running mode) or
|
||||||
|
* <code>STOPPED</code>.
|
||||||
|
*/
|
||||||
|
private void timedOut() {
|
||||||
|
Logger.global.finer("timed out");
|
||||||
|
fCurrentTimeoutState.setTimedOut(true);
|
||||||
|
fDisplay.wake(); // wake up call!
|
||||||
|
if (fKeepRunningOnTimeout)
|
||||||
|
checkedTransition(RUNNING, IDLE);
|
||||||
|
else
|
||||||
|
checkedTransition(RUNNING, STOPPED);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits while the state is <code>IDLE</code>, then returns. The
|
||||||
|
* state must not be <code>RUNNING</code> when calling this
|
||||||
|
* method. The state is either <code>STOPPED</code> or
|
||||||
|
* <code>RUNNING</code> when the method returns.
|
||||||
|
*
|
||||||
|
* @throws InterruptedException if the thread was interrupted
|
||||||
|
* @throws ThreadChangedException if the thread has changed while on
|
||||||
|
* hold
|
||||||
|
*/
|
||||||
|
private void tryHold() throws InterruptedException, ThreadChangedException {
|
||||||
|
while (isState(IDLE)) {
|
||||||
|
fMutex.wait(0);
|
||||||
|
checkThread();
|
||||||
|
}
|
||||||
|
assertStates(STOPPED | RUNNING);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
fCurrentThread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transitions to <code>nextState</code> if the current state is one of
|
||||||
|
* <code>possibleStates</code>. Returns <code>true</code> if the
|
||||||
|
* transition happened, <code>false</code> otherwise.
|
||||||
|
*
|
||||||
|
* @param possibleStates the states which trigger a transition
|
||||||
|
* @param nextState the state to transition to
|
||||||
|
* @return <code>true</code> if the transition happened,
|
||||||
|
* <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
private boolean tryTransition(int possibleStates, int nextState) {
|
||||||
|
if (isState(possibleStates)) {
|
||||||
|
Logger.global.finer(name(fState) + " > " + name(nextState) + " (" + name(possibleStates) + ")");
|
||||||
|
fState= nextState;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Logger.global.finest("noTransition" + name(fState) + " !> " + name(nextState) + " (" + name(possibleStates) + ")");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the <code>possibleStates</code> and throws an assertion if it is
|
||||||
|
* not met, then transitions to <code>nextState</code>.
|
||||||
|
*
|
||||||
|
* @param possibleStates the allowed states
|
||||||
|
* @param nextState the state to transition to
|
||||||
|
*/
|
||||||
|
private void checkedTransition(int possibleStates, int nextState) {
|
||||||
|
assertStates(possibleStates);
|
||||||
|
Logger.global.finer(name(fState) + " > " + name(nextState));
|
||||||
|
fState= nextState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements state consistency checking.
|
||||||
|
*
|
||||||
|
* @param states the allowed states
|
||||||
|
* @throws junit.framework.AssertionFailedError if the current state is not
|
||||||
|
* in <code>states</code>
|
||||||
|
*/
|
||||||
|
private void assertStates(int states) {
|
||||||
|
Assert.assertTrue("illegal state", isState(states));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Answers <code>true</code> if the current state is in the given
|
||||||
|
* <code>states</code>.
|
||||||
|
*
|
||||||
|
* @param states the possible states
|
||||||
|
* @return <code>true</code> if the current state is in the given states,
|
||||||
|
* <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
private boolean isState(int states) {
|
||||||
|
return (states & fState) == fState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pretty print the given states.
|
||||||
|
*
|
||||||
|
* @param states the states
|
||||||
|
* @return a string representation of the states
|
||||||
|
*/
|
||||||
|
private String name(int states) {
|
||||||
|
StringBuffer buf= new StringBuffer();
|
||||||
|
boolean comma= false;
|
||||||
|
if ((states & RUNNING) == RUNNING) {
|
||||||
|
buf.append("RUNNING");
|
||||||
|
comma= true;
|
||||||
|
}
|
||||||
|
if ((states & STOPPED) == STOPPED) {
|
||||||
|
if (comma)
|
||||||
|
buf.append(",");
|
||||||
|
buf.append("STOPPED");
|
||||||
|
comma= true;
|
||||||
|
}
|
||||||
|
if ((states & IDLE) == IDLE) {
|
||||||
|
if (comma)
|
||||||
|
buf.append(",");
|
||||||
|
buf.append("IDLE");
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,508 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IContainer;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IFolder;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.IJobManager;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IWidgetTokenKeeper;
|
||||||
|
import org.eclipse.jface.text.IWidgetTokenOwner;
|
||||||
|
import org.eclipse.jface.text.reconciler.AbstractReconciler;
|
||||||
|
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
|
||||||
|
import org.eclipse.jface.text.reconciler.MonoReconciler;
|
||||||
|
import org.eclipse.jface.text.source.SourceViewer;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.ui.IEditorInput;
|
||||||
|
import org.eclipse.ui.IEditorPart;
|
||||||
|
import org.eclipse.ui.IEditorReference;
|
||||||
|
import org.eclipse.ui.IViewReference;
|
||||||
|
import org.eclipse.ui.IWorkbench;
|
||||||
|
import org.eclipse.ui.IWorkbenchPage;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchPartSite;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.PartInitException;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
import org.eclipse.ui.WorkbenchException;
|
||||||
|
import org.eclipse.ui.dialogs.IOverwriteQuery;
|
||||||
|
import org.eclipse.ui.ide.IDE;
|
||||||
|
import org.eclipse.ui.texteditor.AbstractTextEditor;
|
||||||
|
import org.eclipse.ui.texteditor.IDocumentProvider;
|
||||||
|
import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
|
import org.eclipse.ui.wizards.datatransfer.FileSystemStructureProvider;
|
||||||
|
import org.eclipse.ui.wizards.datatransfer.IImportStructureProvider;
|
||||||
|
import org.eclipse.ui.wizards.datatransfer.ImportOperation;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.model.ICProject;
|
||||||
|
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
|
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CReconcilingStrategy;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from org.eclipse.jdt.text.tests.performance.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class EditorTestHelper {
|
||||||
|
|
||||||
|
private static class ImportOverwriteQuery implements IOverwriteQuery {
|
||||||
|
public String queryOverwrite(String file) {
|
||||||
|
return ALL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String TEXT_EDITOR_ID= "org.eclipse.ui.DefaultTextEditor";
|
||||||
|
|
||||||
|
public static final String C_EDITOR_ID= "org.eclipse.cdt.ui.editor.CEditor";
|
||||||
|
|
||||||
|
public static final String RESOURCE_PERSPECTIVE_ID= "org.eclipse.ui.resourcePerspective";
|
||||||
|
|
||||||
|
public static final String C_PERSPECTIVE_ID= "org.eclipse.cdt.ui.CPerspective";
|
||||||
|
|
||||||
|
public static final String OUTLINE_VIEW_ID= "org.eclipse.ui.views.ContentOutline";
|
||||||
|
|
||||||
|
public static final String C_VIEW_ID= "org.eclipse.cdt.ui.CView";
|
||||||
|
|
||||||
|
public static final String NAVIGATOR_VIEW_ID= "org.eclipse.ui.views.ResourceNavigator";
|
||||||
|
|
||||||
|
public static final String INTRO_VIEW_ID= "org.eclipse.ui.internal.introview";
|
||||||
|
|
||||||
|
public static IEditorPart openInEditor(IFile file, boolean runEventLoop) throws PartInitException {
|
||||||
|
IEditorPart part= IDE.openEditor(getActivePage(), file);
|
||||||
|
if (runEventLoop)
|
||||||
|
runEventQueue(part);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEditorPart openInEditor(IFile file, String editorId, boolean runEventLoop) throws PartInitException {
|
||||||
|
IEditorPart part= IDE.openEditor(getActivePage(), file, editorId);
|
||||||
|
if (runEventLoop)
|
||||||
|
runEventQueue(part);
|
||||||
|
return part;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractTextEditor[] openInEditor(IFile[] files, String editorId) throws PartInitException {
|
||||||
|
AbstractTextEditor editors[]= new AbstractTextEditor[files.length];
|
||||||
|
for (int i= 0; i < files.length; i++) {
|
||||||
|
editors[i]= (AbstractTextEditor) openInEditor(files[i], editorId, true);
|
||||||
|
joinReconciler(getSourceViewer(editors[i]), 100, 10000, 100);
|
||||||
|
}
|
||||||
|
return editors;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IDocument getDocument(ITextEditor editor) {
|
||||||
|
IDocumentProvider provider= editor.getDocumentProvider();
|
||||||
|
IEditorInput input= editor.getEditorInput();
|
||||||
|
return provider.getDocument(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void revertEditor(ITextEditor editor, boolean runEventQueue) {
|
||||||
|
editor.doRevertToSaved();
|
||||||
|
if (runEventQueue)
|
||||||
|
runEventQueue(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeEditor(IEditorPart editor) {
|
||||||
|
IWorkbenchPartSite site;
|
||||||
|
IWorkbenchPage page;
|
||||||
|
if (editor != null && (site= editor.getSite()) != null && (page= site.getPage()) != null)
|
||||||
|
page.closeEditor(editor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeAllEditors() {
|
||||||
|
IWorkbenchWindow[] windows= PlatformUI.getWorkbench().getWorkbenchWindows();
|
||||||
|
for (int i= 0; i < windows.length; i++) {
|
||||||
|
IWorkbenchPage[] pages= windows[i].getPages();
|
||||||
|
for (int j= 0; j < pages.length; j++) {
|
||||||
|
IEditorReference[] editorReferences= pages[j].getEditorReferences();
|
||||||
|
for (int k= 0; k < editorReferences.length; k++)
|
||||||
|
closeEditor(editorReferences[k].getEditor(false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the event queue on the current display until it is empty.
|
||||||
|
*/
|
||||||
|
public static void runEventQueue() {
|
||||||
|
IWorkbenchWindow window= getActiveWorkbenchWindow();
|
||||||
|
if (window != null)
|
||||||
|
runEventQueue(window.getShell());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(IWorkbenchPart part) {
|
||||||
|
runEventQueue(part.getSite().getShell());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(Shell shell) {
|
||||||
|
runEventQueue(shell.getDisplay());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(Display display) {
|
||||||
|
while (display.readAndDispatch()) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the event queue on the current display and lets it sleep until the
|
||||||
|
* timeout elapses.
|
||||||
|
*
|
||||||
|
* @param millis the timeout in milliseconds
|
||||||
|
*/
|
||||||
|
public static void runEventQueue(long millis) {
|
||||||
|
runEventQueue(getActiveDisplay(), millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(IWorkbenchPart part, long millis) {
|
||||||
|
runEventQueue(part.getSite().getShell(), millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(Shell shell, long millis) {
|
||||||
|
runEventQueue(shell.getDisplay(), millis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void runEventQueue(Display display, long minTime) {
|
||||||
|
if (display != null) {
|
||||||
|
DisplayHelper.sleep(display, minTime);
|
||||||
|
} else {
|
||||||
|
sleep((int) minTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWorkbenchWindow getActiveWorkbenchWindow() {
|
||||||
|
return PlatformUI.getWorkbench().getActiveWorkbenchWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forceFocus() {
|
||||||
|
IWorkbenchWindow window= getActiveWorkbenchWindow();
|
||||||
|
if (window == null) {
|
||||||
|
IWorkbenchWindow[] wbWindows= PlatformUI.getWorkbench().getWorkbenchWindows();
|
||||||
|
if (wbWindows.length == 0)
|
||||||
|
return;
|
||||||
|
window= wbWindows[0];
|
||||||
|
}
|
||||||
|
Shell shell= window.getShell();
|
||||||
|
if (shell != null && !shell.isDisposed()) {
|
||||||
|
shell.forceActive();
|
||||||
|
shell.forceFocus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IWorkbenchPage getActivePage() {
|
||||||
|
IWorkbenchWindow window= getActiveWorkbenchWindow();
|
||||||
|
return window != null ? window.getActivePage() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Display getActiveDisplay() {
|
||||||
|
IWorkbenchWindow window= getActiveWorkbenchWindow();
|
||||||
|
return window != null ? window.getShell().getDisplay() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void joinBackgroundActivities(AbstractTextEditor editor) throws CoreException {
|
||||||
|
joinBackgroundActivities(getSourceViewer(editor));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void joinBackgroundActivities(SourceViewer sourceViewer) throws CoreException {
|
||||||
|
joinBackgroundActivities();
|
||||||
|
joinReconciler(sourceViewer, 500, 0, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void joinBackgroundActivities() throws CoreException {
|
||||||
|
// Join Building
|
||||||
|
Logger.global.entering("EditorTestHelper", "joinBackgroundActivities");
|
||||||
|
Logger.global.finer("join builder");
|
||||||
|
boolean interrupted= true;
|
||||||
|
while (interrupted) {
|
||||||
|
try {
|
||||||
|
Platform.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null);
|
||||||
|
interrupted= false;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
interrupted= true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Join indexing
|
||||||
|
Logger.global.finer("join indexer");
|
||||||
|
// new SearchEngine().searchAllTypeNames(
|
||||||
|
// null,
|
||||||
|
// "XXXXXXXXX".toCharArray(), // make sure we search a concrete name. This is faster according to Kent
|
||||||
|
// SearchPattern.R_EXACT_MATCH,
|
||||||
|
// IJavaSearchConstants.CLASS,
|
||||||
|
// SearchEngine.createJavaSearchScope(new ICElement[0]),
|
||||||
|
// new Requestor(),
|
||||||
|
// IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH,
|
||||||
|
// null);
|
||||||
|
// Join jobs
|
||||||
|
joinJobs(0, 0, 500);
|
||||||
|
Logger.global.exiting("EditorTestHelper", "joinBackgroundActivities");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean joinJobs(long minTime, long maxTime, long intervalTime) {
|
||||||
|
Logger.global.entering("EditorTestHelper", "joinJobs");
|
||||||
|
runEventQueue(minTime);
|
||||||
|
|
||||||
|
DisplayHelper helper= new DisplayHelper() {
|
||||||
|
public boolean condition() {
|
||||||
|
return allJobsQuiet();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
boolean quiet= helper.waitForCondition(getActiveDisplay(), maxTime > 0 ? maxTime : Long.MAX_VALUE, intervalTime);
|
||||||
|
Logger.global.exiting("EditorTestHelper", "joinJobs", new Boolean(quiet));
|
||||||
|
return quiet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void sleep(int intervalTime) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(intervalTime);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean allJobsQuiet() {
|
||||||
|
IJobManager jobManager= Platform.getJobManager();
|
||||||
|
Job[] jobs= jobManager.find(null);
|
||||||
|
for (int i= 0; i < jobs.length; i++) {
|
||||||
|
Job job= jobs[i];
|
||||||
|
int state= job.getState();
|
||||||
|
if (state == Job.RUNNING || state == Job.WAITING) {
|
||||||
|
Logger.global.finest(job.toString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isViewShown(String viewId) {
|
||||||
|
return getActivePage().findViewReference(viewId) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean showView(String viewId, boolean show) throws PartInitException {
|
||||||
|
IWorkbenchPage activePage= getActivePage();
|
||||||
|
IViewReference view= activePage.findViewReference(viewId);
|
||||||
|
boolean shown= view != null;
|
||||||
|
if (shown != show)
|
||||||
|
if (show)
|
||||||
|
activePage.showView(viewId);
|
||||||
|
else
|
||||||
|
activePage.hideView(view);
|
||||||
|
return shown;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void bringToTop() {
|
||||||
|
getActiveWorkbenchWindow().getShell().forceActive();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void forceReconcile(SourceViewer sourceViewer) {
|
||||||
|
Accessor reconcilerAccessor= new Accessor(getReconciler(sourceViewer), AbstractReconciler.class);
|
||||||
|
reconcilerAccessor.invoke("forceReconciling", new Object[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean joinReconciler(SourceViewer sourceViewer, long minTime, long maxTime, long intervalTime) {
|
||||||
|
Logger.global.entering("EditorTestHelper", "joinReconciler");
|
||||||
|
runEventQueue(minTime);
|
||||||
|
|
||||||
|
AbstractReconciler reconciler= getReconciler(sourceViewer);
|
||||||
|
if (reconciler == null)
|
||||||
|
return true;
|
||||||
|
final Accessor backgroundThreadAccessor= getBackgroundThreadAccessor(reconciler);
|
||||||
|
final Accessor cReconcilerAccessor;
|
||||||
|
if (reconciler instanceof MonoReconciler) {
|
||||||
|
IReconcilingStrategy strategy= reconciler.getReconcilingStrategy(IDocument.DEFAULT_CONTENT_TYPE);
|
||||||
|
if (strategy instanceof CReconcilingStrategy) {
|
||||||
|
cReconcilerAccessor= new Accessor(strategy, CReconcilingStrategy.class);
|
||||||
|
} else {
|
||||||
|
cReconcilerAccessor= null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cReconcilerAccessor= null;
|
||||||
|
}
|
||||||
|
DisplayHelper helper= new DisplayHelper() {
|
||||||
|
public boolean condition() {
|
||||||
|
return !isRunning(cReconcilerAccessor, backgroundThreadAccessor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
boolean finished= helper.waitForCondition(getActiveDisplay(), maxTime > 0 ? maxTime : Long.MAX_VALUE, intervalTime);
|
||||||
|
Logger.global.exiting("EditorTestHelper", "joinReconciler", new Boolean(finished));
|
||||||
|
return finished;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractReconciler getReconciler(SourceViewer sourceViewer) {
|
||||||
|
return (AbstractReconciler) new Accessor(sourceViewer, SourceViewer.class).get("fReconciler");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SourceViewer getSourceViewer(AbstractTextEditor editor) {
|
||||||
|
SourceViewer sourceViewer= (SourceViewer) new Accessor(editor, AbstractTextEditor.class).invoke("getSourceViewer", new Object[0]);
|
||||||
|
return sourceViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Accessor getBackgroundThreadAccessor(AbstractReconciler reconciler) {
|
||||||
|
Object backgroundThread= new Accessor(reconciler, AbstractReconciler.class).get("fThread");
|
||||||
|
return new Accessor(backgroundThread, backgroundThread.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isRunning(Accessor cReconcilerAccessor, Accessor backgroundThreadAccessor) {
|
||||||
|
return (cReconcilerAccessor != null ? !isInitialProcessDone(cReconcilerAccessor) : false) || isDirty(backgroundThreadAccessor) || isActive(backgroundThreadAccessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isInitialProcessDone(Accessor cReconcilerAccessor) {
|
||||||
|
return ((Boolean) cReconcilerAccessor.get("fInitialProcessDone")).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isDirty(Accessor backgroundThreadAccessor) {
|
||||||
|
return ((Boolean) backgroundThreadAccessor.invoke("isDirty", new Object[0])).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isActive(Accessor backgroundThreadAccessor) {
|
||||||
|
return ((Boolean) backgroundThreadAccessor.invoke("isActive", new Object[0])).booleanValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String showPerspective(String perspective) throws WorkbenchException {
|
||||||
|
String shownPerspective= getActivePage().getPerspective().getId();
|
||||||
|
if (!perspective.equals(shownPerspective)) {
|
||||||
|
IWorkbench workbench= PlatformUI.getWorkbench();
|
||||||
|
IWorkbenchWindow activeWindow= workbench.getActiveWorkbenchWindow();
|
||||||
|
workbench.showPerspective(perspective, activeWindow);
|
||||||
|
}
|
||||||
|
return shownPerspective;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void closeAllPopUps(SourceViewer sourceViewer) {
|
||||||
|
IWidgetTokenKeeper tokenKeeper= new IWidgetTokenKeeper() {
|
||||||
|
public boolean requestWidgetToken(IWidgetTokenOwner owner) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
sourceViewer.requestWidgetToken(tokenKeeper, Integer.MAX_VALUE);
|
||||||
|
sourceViewer.releaseWidgetToken(tokenKeeper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void resetFolding() {
|
||||||
|
CUIPlugin.getDefault().getPreferenceStore().setToDefault(PreferenceConstants.EDITOR_FOLDING_ENABLED);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enableFolding(boolean value) {
|
||||||
|
IPreferenceStore preferenceStore= CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
boolean oldValue= preferenceStore.getBoolean(PreferenceConstants.EDITOR_FOLDING_ENABLED);
|
||||||
|
if (value != oldValue)
|
||||||
|
preferenceStore.setValue(PreferenceConstants.EDITOR_FOLDING_ENABLED, value);
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICProject createCProject(String project, String externalSourceFolder) throws CoreException {
|
||||||
|
return createCProject(project, externalSourceFolder, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ICProject createCProject(String project, String externalSourceFolder, boolean linkSourceFolder) throws CoreException {
|
||||||
|
ICProject cProject= CProjectHelper.createCProject(project, "bin");
|
||||||
|
IFolder folder;
|
||||||
|
if (linkSourceFolder)
|
||||||
|
folder= ResourceHelper.createLinkedFolder((IProject) cProject.getUnderlyingResource(), new Path("src"), CTestPlugin.getDefault(), new Path(externalSourceFolder));
|
||||||
|
else {
|
||||||
|
folder= ((IProject) cProject.getUnderlyingResource()).getFolder("src");
|
||||||
|
importFilesFromDirectory(FileTool.getFileInPlugin(CTestPlugin.getDefault(), new Path(externalSourceFolder)), folder.getFullPath(), null);
|
||||||
|
}
|
||||||
|
Assert.assertNotNull(folder);
|
||||||
|
Assert.assertTrue(folder.exists());
|
||||||
|
CProjectHelper.addCContainer(cProject, "src");
|
||||||
|
return cProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile[] findFiles(IResource resource) throws CoreException {
|
||||||
|
List files= new ArrayList();
|
||||||
|
findFiles(resource, files);
|
||||||
|
return (IFile[]) files.toArray(new IFile[files.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findFiles(IResource resource, List files) throws CoreException {
|
||||||
|
if (resource instanceof IFile) {
|
||||||
|
files.add(resource);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (resource instanceof IContainer) {
|
||||||
|
IResource[] resources= ((IContainer) resource).members();
|
||||||
|
for (int i= 0; i < resources.length; i++)
|
||||||
|
findFiles(resources[i], files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setDialogEnabled(String id, boolean enabled) {
|
||||||
|
// boolean wasEnabled= OptionalMessageDialog.isDialogEnabled(id);
|
||||||
|
// if (wasEnabled != enabled)
|
||||||
|
// OptionalMessageDialog.setDialogEnabled(id, enabled);
|
||||||
|
// return wasEnabled;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void importFilesFromDirectory(File rootDir, IPath destPath, IProgressMonitor monitor) throws CoreException {
|
||||||
|
try {
|
||||||
|
IImportStructureProvider structureProvider= FileSystemStructureProvider.INSTANCE;
|
||||||
|
List files= new ArrayList(100);
|
||||||
|
addFiles(rootDir, files);
|
||||||
|
ImportOperation op= new ImportOperation(destPath, rootDir, structureProvider, new ImportOverwriteQuery(), files);
|
||||||
|
op.setCreateContainerStructure(false);
|
||||||
|
op.run(monitor);
|
||||||
|
} catch (Exception x) {
|
||||||
|
throw newCoreException(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CoreException newCoreException(Throwable x) {
|
||||||
|
return new CoreException(new Status(IStatus.ERROR, CTestPlugin.PLUGIN_ID, -1, "", x));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void addFiles(File dir, List collection) throws IOException {
|
||||||
|
File[] files= dir.listFiles();
|
||||||
|
List subDirs= new ArrayList(2);
|
||||||
|
for (int i= 0; i < files.length; i++) {
|
||||||
|
if (files[i].isFile()) {
|
||||||
|
collection.add(files[i]);
|
||||||
|
} else if (files[i].isDirectory()) {
|
||||||
|
subDirs.add(files[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Iterator iter= subDirs.iterator();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
File subDir= (File)iter.next();
|
||||||
|
addFiles(subDir, collection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Plugin;
|
||||||
|
|
||||||
|
import org.eclipse.core.filebuffers.FileBuffers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from org.eclipse.core.filebuffers.tests.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class FileTool {
|
||||||
|
|
||||||
|
private final static int MAX_RETRY= 5;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A buffer.
|
||||||
|
*/
|
||||||
|
private static byte[] buffer = new byte[8192];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unzips the given zip file to the given destination directory
|
||||||
|
* extracting only those entries the pass through the given
|
||||||
|
* filter.
|
||||||
|
*
|
||||||
|
* @param zipFile the zip file to unzip
|
||||||
|
* @param dstDir the destination directory
|
||||||
|
* @throws IOException in case of problem
|
||||||
|
*/
|
||||||
|
public static void unzip(ZipFile zipFile, File dstDir) throws IOException {
|
||||||
|
unzip(zipFile, dstDir, dstDir, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void unzip(ZipFile zipFile, File rootDstDir, File dstDir, int depth) throws IOException {
|
||||||
|
|
||||||
|
Enumeration entries = zipFile.entries();
|
||||||
|
|
||||||
|
try {
|
||||||
|
while(entries.hasMoreElements()){
|
||||||
|
ZipEntry entry = (ZipEntry)entries.nextElement();
|
||||||
|
if(entry.isDirectory()){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String entryName = entry.getName();
|
||||||
|
File file = new File(dstDir, changeSeparator(entryName, '/', File.separatorChar));
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
InputStream src = null;
|
||||||
|
OutputStream dst = null;
|
||||||
|
try {
|
||||||
|
src = zipFile.getInputStream(entry);
|
||||||
|
dst = new FileOutputStream(file);
|
||||||
|
transferData(src, dst);
|
||||||
|
} finally {
|
||||||
|
if(dst != null){
|
||||||
|
try {
|
||||||
|
dst.close();
|
||||||
|
} catch(IOException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(src != null){
|
||||||
|
try {
|
||||||
|
src.close();
|
||||||
|
} catch(IOException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
zipFile.close();
|
||||||
|
} catch(IOException e){
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the given file path with its separator
|
||||||
|
* character changed from the given old separator to the
|
||||||
|
* given new separator.
|
||||||
|
*
|
||||||
|
* @param path a file path
|
||||||
|
* @param oldSeparator a path separator character
|
||||||
|
* @param newSeparator a path separator character
|
||||||
|
* @return the file path with its separator character
|
||||||
|
* changed from the given old separator to the given new
|
||||||
|
* separator
|
||||||
|
*/
|
||||||
|
public static String changeSeparator(String path, char oldSeparator, char newSeparator){
|
||||||
|
return path.replace(oldSeparator, newSeparator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all bytes in the given source file to
|
||||||
|
* the given destination file.
|
||||||
|
*
|
||||||
|
* @param source the given source file
|
||||||
|
* @param destination the given destination file
|
||||||
|
* @throws IOException in case of error
|
||||||
|
*/
|
||||||
|
public static void transferData(File source, File destination) throws IOException {
|
||||||
|
destination.getParentFile().mkdirs();
|
||||||
|
InputStream is = null;
|
||||||
|
OutputStream os = null;
|
||||||
|
try {
|
||||||
|
is = new FileInputStream(source);
|
||||||
|
os = new FileOutputStream(destination);
|
||||||
|
transferData(is, os);
|
||||||
|
} finally {
|
||||||
|
if(os != null)
|
||||||
|
os.close();
|
||||||
|
if(is != null)
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all bytes in the given source stream to
|
||||||
|
* the given destination stream. Neither streams
|
||||||
|
* are closed.
|
||||||
|
*
|
||||||
|
* @param source the given source stream
|
||||||
|
* @param destination the given destination stream
|
||||||
|
* @throws IOException in case of error
|
||||||
|
*/
|
||||||
|
public static void transferData(InputStream source, OutputStream destination) throws IOException {
|
||||||
|
int bytesRead = 0;
|
||||||
|
while(bytesRead != -1){
|
||||||
|
bytesRead = source.read(buffer, 0, buffer.length);
|
||||||
|
if(bytesRead != -1){
|
||||||
|
destination.write(buffer, 0, bytesRead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the given source file to the given destination file.
|
||||||
|
*
|
||||||
|
* @param src the given source file
|
||||||
|
* @param dst the given destination file
|
||||||
|
* @throws IOException in case of error
|
||||||
|
*/
|
||||||
|
public static void copy(File src, File dst) throws IOException {
|
||||||
|
if(src.isDirectory()){
|
||||||
|
String[] srcChildren = src.list();
|
||||||
|
for(int i = 0; i < srcChildren.length; ++i){
|
||||||
|
File srcChild= new File(src, srcChildren[i]);
|
||||||
|
File dstChild= new File(dst, srcChildren[i]);
|
||||||
|
copy(srcChild, dstChild);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
transferData(src, dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File getFileInPlugin(Plugin plugin, IPath path) {
|
||||||
|
try {
|
||||||
|
URL installURL= plugin.getBundle().getEntry(path.toString());
|
||||||
|
URL localURL= Platform.asLocalURL(installURL);
|
||||||
|
return new File(localURL.getFile());
|
||||||
|
} catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static File createTempFileInPlugin(Plugin plugin, IPath path) {
|
||||||
|
IPath stateLocation= plugin.getStateLocation();
|
||||||
|
stateLocation= stateLocation.append(path);
|
||||||
|
return stateLocation.toFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringBuffer read(String fileName) throws IOException {
|
||||||
|
return read(new FileReader(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringBuffer read(Reader reader) throws IOException {
|
||||||
|
StringBuffer s= new StringBuffer();
|
||||||
|
try {
|
||||||
|
char[] charBuffer= new char[8196];
|
||||||
|
int chars= reader.read(charBuffer);
|
||||||
|
while (chars != -1) {
|
||||||
|
s.append(charBuffer, 0, chars);
|
||||||
|
chars= reader.read(charBuffer);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
reader.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(String fileName, StringBuffer content) throws IOException {
|
||||||
|
Writer writer= new FileWriter(fileName);
|
||||||
|
try {
|
||||||
|
writer.write(content.toString());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
writer.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(IPath path) throws CoreException {
|
||||||
|
File file= FileBuffers.getSystemFileAtLocation(path);
|
||||||
|
delete(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(File file) throws CoreException {
|
||||||
|
if (file.exists()) {
|
||||||
|
for (int i= 0; i < MAX_RETRY; i++) {
|
||||||
|
if (file.delete())
|
||||||
|
i= MAX_RETRY;
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000); // sleep a second
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import org.eclipse.core.filebuffers.manipulation.ContainerCreator;
|
||||||
|
import org.eclipse.core.resources.IContainer;
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IFolder;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
|
import org.eclipse.core.resources.IResource;
|
||||||
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IPath;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.Plugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.testplugin.CTestPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from org.eclipse.core.filebuffers.tests.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class ResourceHelper {
|
||||||
|
|
||||||
|
private final static IProgressMonitor NULL_MONITOR= new NullProgressMonitor();
|
||||||
|
private static final int MAX_RETRY= 5;
|
||||||
|
|
||||||
|
public static IProject createProject(String projectName) throws CoreException {
|
||||||
|
|
||||||
|
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
|
||||||
|
IProject project= root.getProject(projectName);
|
||||||
|
if (!project.exists())
|
||||||
|
project.create(NULL_MONITOR);
|
||||||
|
else
|
||||||
|
project.refreshLocal(IResource.DEPTH_INFINITE, null);
|
||||||
|
|
||||||
|
if (!project.isOpen())
|
||||||
|
project.open(NULL_MONITOR);
|
||||||
|
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteProject(String projectName) throws CoreException {
|
||||||
|
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
|
||||||
|
IProject project= root.getProject(projectName);
|
||||||
|
if (project.exists())
|
||||||
|
delete(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(final IProject project) throws CoreException {
|
||||||
|
delete(project, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(final IProject project, boolean deleteContent) throws CoreException {
|
||||||
|
for (int i= 0; i < MAX_RETRY; i++) {
|
||||||
|
try {
|
||||||
|
project.delete(deleteContent, true, NULL_MONITOR);
|
||||||
|
i= MAX_RETRY;
|
||||||
|
} catch (CoreException x) {
|
||||||
|
if (i == MAX_RETRY - 1) {
|
||||||
|
CTestPlugin.getDefault().getLog().log(x.getStatus());
|
||||||
|
// throw x;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(1000); // sleep a second
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFolder createFolder(String portableFolderPath) throws CoreException {
|
||||||
|
ContainerCreator creator= new ContainerCreator(ResourcesPlugin.getWorkspace(), new Path(portableFolderPath));
|
||||||
|
IContainer container= creator.createContainer(NULL_MONITOR);
|
||||||
|
if (container instanceof IFolder)
|
||||||
|
return (IFolder) container;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile createFile(IFolder folder, String name, String contents) throws CoreException {
|
||||||
|
return createFile(folder.getFile(name), name, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile createFile(IProject project, String name, String contents) throws CoreException {
|
||||||
|
return createFile(project.getFile(name), name, contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IFile createFile(IFile file, String name, String contents) throws CoreException {
|
||||||
|
if (contents == null)
|
||||||
|
contents= "";
|
||||||
|
InputStream inputStream= new java.io.StringBufferInputStream(contents);
|
||||||
|
file.create(inputStream, true, NULL_MONITOR);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile createLinkedFile(IContainer container, IPath linkPath, File linkedFileTarget) throws CoreException {
|
||||||
|
IFile iFile= container.getFile(linkPath);
|
||||||
|
iFile.createLink(new Path(linkedFileTarget.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR);
|
||||||
|
return iFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile createLinkedFile(IContainer container, IPath linkPath, Plugin plugin, IPath linkedFileTargetPath) throws CoreException {
|
||||||
|
File file= FileTool.getFileInPlugin(plugin, linkedFileTargetPath);
|
||||||
|
IFile iFile= container.getFile(linkPath);
|
||||||
|
iFile.createLink(new Path(file.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR);
|
||||||
|
return iFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFolder createLinkedFolder(IContainer container, IPath linkPath, File linkedFolderTarget) throws CoreException {
|
||||||
|
IFolder folder= container.getFolder(linkPath);
|
||||||
|
folder.createLink(new Path(linkedFolderTarget.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR);
|
||||||
|
return folder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFolder createLinkedFolder(IContainer container, IPath linkPath, Plugin plugin, IPath linkedFolderTargetPath) throws CoreException {
|
||||||
|
File file= FileTool.getFileInPlugin(plugin, linkedFolderTargetPath);
|
||||||
|
IFolder iFolder= container.getFolder(linkPath);
|
||||||
|
iFolder.createLink(new Path(file.getAbsolutePath()), IResource.ALLOW_MISSING_LOCAL, NULL_MONITOR);
|
||||||
|
return iFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IProject createLinkedProject(String projectName, Plugin plugin, IPath linkPath) throws CoreException {
|
||||||
|
IWorkspace workspace= ResourcesPlugin.getWorkspace();
|
||||||
|
IProject project= workspace.getRoot().getProject(projectName);
|
||||||
|
|
||||||
|
IProjectDescription desc= workspace.newProjectDescription(projectName);
|
||||||
|
File file= FileTool.getFileInPlugin(plugin, linkPath);
|
||||||
|
IPath projectLocation= new Path(file.getAbsolutePath());
|
||||||
|
if (Platform.getLocation().equals(projectLocation))
|
||||||
|
projectLocation= null;
|
||||||
|
desc.setLocation(projectLocation);
|
||||||
|
|
||||||
|
project.create(desc, NULL_MONITOR);
|
||||||
|
if (!project.isOpen())
|
||||||
|
project.open(NULL_MONITOR);
|
||||||
|
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,252 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.Reader;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.zip.ZipException;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
|
||||||
|
import org.eclipse.core.resources.IFile;
|
||||||
|
import org.eclipse.core.resources.IProject;
|
||||||
|
import org.eclipse.core.resources.IProjectDescription;
|
||||||
|
import org.eclipse.core.resources.IWorkspace;
|
||||||
|
import org.eclipse.core.resources.IWorkspaceRoot;
|
||||||
|
import org.eclipse.core.resources.IncrementalProjectBuilder;
|
||||||
|
import org.eclipse.core.resources.ResourcesPlugin;
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.Path;
|
||||||
|
import org.eclipse.core.runtime.Plugin;
|
||||||
|
import org.eclipse.core.runtime.Preferences;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from org.eclipse.jdt.text.tests.performance.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class ResourceTestHelper {
|
||||||
|
|
||||||
|
public static final int FAIL_IF_EXISTS= 0;
|
||||||
|
|
||||||
|
public static final int OVERWRITE_IF_EXISTS= 1;
|
||||||
|
|
||||||
|
public static final int SKIP_IF_EXISTS= 2;
|
||||||
|
|
||||||
|
private static final int DELETE_MAX_RETRY= 5;
|
||||||
|
|
||||||
|
private static final long DELETE_RETRY_DELAY= 1000;
|
||||||
|
|
||||||
|
public static void replicate(String src, String destPrefix, String destSuffix, int n, int ifExists) throws CoreException {
|
||||||
|
for (int i= 0; i < n; i++)
|
||||||
|
copy(src, destPrefix + i + destSuffix, ifExists);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copy(String src, String dest) throws CoreException {
|
||||||
|
copy(src, dest, FAIL_IF_EXISTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copy(String src, String dest, int ifExists) throws CoreException {
|
||||||
|
if (handleExisting(dest, ifExists))
|
||||||
|
getFile(src).copy(new Path(dest), true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean handleExisting(String dest, int ifExists) throws CoreException {
|
||||||
|
IFile destFile= getFile(dest);
|
||||||
|
switch (ifExists) {
|
||||||
|
case FAIL_IF_EXISTS:
|
||||||
|
if (destFile.exists())
|
||||||
|
throw new IllegalArgumentException("Destination file exists: " + dest);
|
||||||
|
return true;
|
||||||
|
case OVERWRITE_IF_EXISTS:
|
||||||
|
if (destFile.exists())
|
||||||
|
delete(destFile);
|
||||||
|
return true;
|
||||||
|
case SKIP_IF_EXISTS:
|
||||||
|
if (destFile.exists())
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IFile getFile(String path) {
|
||||||
|
return getRoot().getFile(new Path(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(String file) throws CoreException {
|
||||||
|
delete(getFile(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void delete(IFile file) throws CoreException {
|
||||||
|
CoreException x= null;
|
||||||
|
for (int i= 0; i < DELETE_MAX_RETRY; i++) {
|
||||||
|
try {
|
||||||
|
file.delete(true, null);
|
||||||
|
return;
|
||||||
|
} catch (CoreException x0) {
|
||||||
|
x= x0;
|
||||||
|
try {
|
||||||
|
Thread.sleep(DELETE_RETRY_DELAY);
|
||||||
|
} catch (InterruptedException x1) {
|
||||||
|
// should not happen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void delete(String prefix, String suffix, int n) throws CoreException {
|
||||||
|
for (int i= 0; i < n; i++)
|
||||||
|
delete(prefix + i + suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile findFile(String pathStr) {
|
||||||
|
IFile file= getFile(pathStr);
|
||||||
|
Assert.assertTrue(file != null && file.exists());
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IFile[] findFiles(String prefix, String suffix, int i, int n) {
|
||||||
|
List files= new ArrayList(n);
|
||||||
|
for (int j= i; j < i + n; j++) {
|
||||||
|
String path= prefix + j + suffix;
|
||||||
|
files.add(findFile(path));
|
||||||
|
}
|
||||||
|
return (IFile[]) files.toArray(new IFile[files.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static StringBuffer read(String src) throws IOException, CoreException {
|
||||||
|
return FileTool.read(new InputStreamReader(getFile(src).getContents()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void write(String dest, final String content) throws IOException, CoreException {
|
||||||
|
InputStream stream= new InputStream() {
|
||||||
|
private Reader fReader= new StringReader(content);
|
||||||
|
public int read() throws IOException {
|
||||||
|
return fReader.read();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getFile(dest).create(stream, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void replicate(String src, String destPrefix, String destSuffix, int n, String srcName, String destNamePrefix, int ifExists) throws IOException, CoreException {
|
||||||
|
StringBuffer s= read(src);
|
||||||
|
List positions= identifierPositions(s, srcName);
|
||||||
|
for (int j= 0; j < n; j++) {
|
||||||
|
String dest= destPrefix + j + destSuffix;
|
||||||
|
if (handleExisting(dest, ifExists)) {
|
||||||
|
StringBuffer c= new StringBuffer(s.toString());
|
||||||
|
replacePositions(c, srcName.length(), destNamePrefix + j, positions);
|
||||||
|
write(dest, c.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void copy(String src, String dest, String srcName, String destName, int ifExists) throws IOException, CoreException {
|
||||||
|
if (handleExisting(dest, ifExists)) {
|
||||||
|
StringBuffer buf= read(src);
|
||||||
|
List positions= identifierPositions(buf, srcName);
|
||||||
|
replacePositions(buf, srcName.length(), destName, positions);
|
||||||
|
write(dest, buf.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void replacePositions(StringBuffer c, int origLength, String string, List positions) {
|
||||||
|
int offset= 0;
|
||||||
|
for (Iterator iter= positions.iterator(); iter.hasNext();) {
|
||||||
|
int position= ((Integer) iter.next()).intValue();
|
||||||
|
c.replace(offset + position, offset + position + origLength, string);
|
||||||
|
offset += string.length() - origLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List identifierPositions(StringBuffer buffer, String identifier) {
|
||||||
|
List positions= new ArrayList();
|
||||||
|
int i= -1;
|
||||||
|
while (true) {
|
||||||
|
i= buffer.indexOf(identifier, i + 1);
|
||||||
|
if (i == -1)
|
||||||
|
break;
|
||||||
|
if (i > 0 && Character.isJavaIdentifierPart(buffer.charAt(i - 1)))
|
||||||
|
continue;
|
||||||
|
if (i < buffer.length() - 1 && Character.isJavaIdentifierPart(buffer.charAt(i + identifier.length())))
|
||||||
|
continue;
|
||||||
|
positions.add(new Integer(i));
|
||||||
|
}
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IWorkspaceRoot getRoot() {
|
||||||
|
return ResourcesPlugin.getWorkspace().getRoot();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void incrementalBuild() throws CoreException {
|
||||||
|
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.INCREMENTAL_BUILD, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fullBuild() throws CoreException {
|
||||||
|
ResourcesPlugin.getWorkspace().build(IncrementalProjectBuilder.FULL_BUILD, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean disableAutoBuilding() {
|
||||||
|
return setAutoBuilding(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean enableAutoBuilding() {
|
||||||
|
return setAutoBuilding(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean setAutoBuilding(boolean value) {
|
||||||
|
Preferences preferences= ResourcesPlugin.getPlugin().getPluginPreferences();
|
||||||
|
boolean oldValue= preferences.getBoolean(ResourcesPlugin.PREF_AUTO_BUILDING);
|
||||||
|
if (value != oldValue)
|
||||||
|
preferences.setValue(ResourcesPlugin.PREF_AUTO_BUILDING, value);
|
||||||
|
return oldValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IProject createExistingProject(String projectName) throws CoreException {
|
||||||
|
IWorkspace workspace= ResourcesPlugin.getWorkspace();
|
||||||
|
IProject project= workspace.getRoot().getProject(projectName);
|
||||||
|
IProjectDescription description= workspace.newProjectDescription(projectName);
|
||||||
|
description.setLocation(null);
|
||||||
|
|
||||||
|
project.create(description, null);
|
||||||
|
project.open(null);
|
||||||
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IProject createProjectFromZip(Plugin installationPlugin, String projectZip, String projectName) throws IOException, ZipException, CoreException {
|
||||||
|
String workspacePath= ResourcesPlugin.getWorkspace().getRoot().getLocation().toString() + "/";
|
||||||
|
FileTool.unzip(new ZipFile(FileTool.getFileInPlugin(installationPlugin, new Path(projectZip))), new File(workspacePath));
|
||||||
|
return createExistingProject(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IProject getProject(String projectName) {
|
||||||
|
IWorkspace workspace= ResourcesPlugin.getWorkspace();
|
||||||
|
return workspace.getRoot().getProject(projectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean projectExists(String projectName) {
|
||||||
|
return getProject(projectName).exists();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.ui.tests.text;
|
||||||
|
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.Position;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting tests.
|
||||||
|
*
|
||||||
|
* <p>Derived from JDT.<p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SemanticHighlightingTest extends AbstractSemanticHighlightingTest {
|
||||||
|
|
||||||
|
private static final Class THIS= SemanticHighlightingTest.class;
|
||||||
|
|
||||||
|
public static Test suite() {
|
||||||
|
return new SemanticHighlightingTestSetup(new TestSuite(THIS), "/SHTest/src/SHTest.cpp");
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void testStaticConstFieldHighlighting() throws Exception {
|
||||||
|
// setUpSemanticHighlighting(SemanticHighlightings.STATIC_CONST_FIELD);
|
||||||
|
// Position[] expected= new Position[] {
|
||||||
|
// createPosition(6, 18, 16),
|
||||||
|
// createPosition(35, 37, 16),
|
||||||
|
// };
|
||||||
|
// Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
//// System.out.println(toString(actual));
|
||||||
|
// assertEqualPositions(expected, actual);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testStaticFieldHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.STATIC_FIELD);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(23, 15, 14),
|
||||||
|
createPosition(25, 21, 19),
|
||||||
|
createPosition(41, 21, 20),
|
||||||
|
createPosition(42, 15, 15),
|
||||||
|
createPosition(56, 21, 20),
|
||||||
|
createPosition(57, 15, 15),
|
||||||
|
createPosition(115, 20, 15),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFieldHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.FIELD);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(24, 14, 13),
|
||||||
|
createPosition(26, 8, 8),
|
||||||
|
createPosition(43, 15, 14),
|
||||||
|
createPosition(44, 8, 9),
|
||||||
|
createPosition(58, 15, 14),
|
||||||
|
createPosition(59, 8, 9),
|
||||||
|
createPosition(74, 7, 5),
|
||||||
|
createPosition(75, 7, 5),
|
||||||
|
createPosition(77, 8, 5),
|
||||||
|
createPosition(78, 8, 5),
|
||||||
|
createPosition(86, 8, 11),
|
||||||
|
createPosition(90, 8, 10),
|
||||||
|
createPosition(102, 11, 9),
|
||||||
|
createPosition(107, 11, 8),
|
||||||
|
createPosition(112, 7, 11),
|
||||||
|
createPosition(114, 7, 10),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMethodDeclarationHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.METHOD_DECLARATION);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(28, 15, 15),
|
||||||
|
createPosition(32, 8, 9),
|
||||||
|
createPosition(46, 15, 16),
|
||||||
|
createPosition(47, 8, 10),
|
||||||
|
createPosition(61, 15, 16),
|
||||||
|
createPosition(62, 8, 10),
|
||||||
|
createPosition(76, 4, 13),
|
||||||
|
createPosition(101, 4, 26),
|
||||||
|
createPosition(101, 20, 10),
|
||||||
|
createPosition(105, 4, 25),
|
||||||
|
createPosition(105, 20, 9),
|
||||||
|
createPosition(110, 4, 32),
|
||||||
|
createPosition(110, 20, 16),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMethodInvocationHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.METHOD_INVOCATION);
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(111, 22, 9),
|
||||||
|
createPosition(113, 21, 8),
|
||||||
|
createPosition(115, 4, 15),
|
||||||
|
};
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void testStaticMethodInvocationHighlighting() throws Exception {
|
||||||
|
// setUpSemanticHighlighting(SemanticHighlightings.STATIC_METHOD_INVOCATION);
|
||||||
|
// Position[] expected= new Position[] {
|
||||||
|
// };
|
||||||
|
// Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
// assertEqualPositions(expected, actual);
|
||||||
|
// }
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
// public void testVirtualMethodInvocationHighlighting() throws Exception {
|
||||||
|
// setUpSemanticHighlighting(SemanticHighlightings.VIRTUAL_METHOD_INVOCATION);
|
||||||
|
// Position[] expected= new Position[] {
|
||||||
|
// createPosition(11, 2, 14),
|
||||||
|
// };
|
||||||
|
// Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
//// System.out.println(toString(actual));
|
||||||
|
// assertEqualPositions(expected, actual);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public void testInheritedMethodInvocationHighlighting() throws Exception {
|
||||||
|
// setUpSemanticHighlighting(SemanticHighlightings.INHERITED_METHOD_INVOCATION);
|
||||||
|
// Position[] expected= new Position[] {
|
||||||
|
// createPosition(12, 2, 8),
|
||||||
|
// createPosition(15, 17, 8),
|
||||||
|
// };
|
||||||
|
// Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
//// System.out.println(toString(actual));
|
||||||
|
// assertEqualPositions(expected, actual);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testLocalVariableDeclarationHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.LOCAL_VARIABLE_DECLARATION);
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(106, 8, 8),
|
||||||
|
createPosition(111, 14, 2),
|
||||||
|
createPosition(113, 13, 2),
|
||||||
|
};
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLocalVariableHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.LOCAL_VARIABLE);
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(112, 4, 2),
|
||||||
|
createPosition(114, 4, 2),
|
||||||
|
};
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testParameterVariableHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.PARAMETER_VARIABLE);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(11, 20, 1),
|
||||||
|
createPosition(28, 35, 3),
|
||||||
|
createPosition(29, 8, 19),
|
||||||
|
createPosition(30, 19, 3),
|
||||||
|
createPosition(76, 21, 4),
|
||||||
|
createPosition(76, 30, 4),
|
||||||
|
createPosition(77, 16, 4),
|
||||||
|
createPosition(78, 16, 4),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTemplateParameterHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.TEMPLATE_PARAMETER);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void testTemplateArgumentHighlighting() throws Exception {
|
||||||
|
// setUpSemanticHighlighting(SemanticHighlightings.TEMPLATE_ARGUMENT);
|
||||||
|
// Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
// Position[] expected= new Position[] {
|
||||||
|
// createPosition(41, 8, 6),
|
||||||
|
// };
|
||||||
|
//// System.out.println(toString(actual));
|
||||||
|
// assertEqualPositions(expected, actual);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public void testEnumHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.ENUM);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(3, 5, 11),
|
||||||
|
createPosition(34, 9, 14),
|
||||||
|
createPosition(49, 9, 15),
|
||||||
|
createPosition(64, 9, 15),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testClassHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.CLASS);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(15, 6, 5),
|
||||||
|
createPosition(16, 6, 5),
|
||||||
|
createPosition(18, 6, 14),
|
||||||
|
createPosition(18, 23, 5),
|
||||||
|
createPosition(18, 30, 5),
|
||||||
|
createPosition(20, 17, 11),
|
||||||
|
createPosition(35, 10, 8),
|
||||||
|
createPosition(36, 10, 9),
|
||||||
|
createPosition(37, 10, 8),
|
||||||
|
createPosition(38, 12, 8),
|
||||||
|
createPosition(50, 10, 9),
|
||||||
|
createPosition(51, 10, 10),
|
||||||
|
createPosition(52, 10, 9),
|
||||||
|
createPosition(53, 12, 9),
|
||||||
|
createPosition(65, 10, 9),
|
||||||
|
createPosition(66, 10, 10),
|
||||||
|
createPosition(67, 10, 9),
|
||||||
|
createPosition(68, 12, 9),
|
||||||
|
createPosition(73, 22, 13),
|
||||||
|
createPosition(82, 19, 24),
|
||||||
|
createPosition(82, 46, 13),
|
||||||
|
createPosition(82, 63, 5),
|
||||||
|
createPosition(85, 7, 9),
|
||||||
|
createPosition(89, 6, 8),
|
||||||
|
createPosition(93, 8, 8),
|
||||||
|
createPosition(111, 4, 9),
|
||||||
|
createPosition(113, 4, 8),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionDeclarationHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.FUNCTION_DECLARATION);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(11, 5, 10),
|
||||||
|
createPosition(12, 12, 16),
|
||||||
|
createPosition(19, 16, 10),
|
||||||
|
createPosition(28, 15, 15),
|
||||||
|
createPosition(32, 8, 9),
|
||||||
|
createPosition(46, 15, 16),
|
||||||
|
createPosition(47, 8, 10),
|
||||||
|
createPosition(61, 15, 16),
|
||||||
|
createPosition(62, 8, 10),
|
||||||
|
createPosition(76, 4, 13),
|
||||||
|
createPosition(97, 8, 13),
|
||||||
|
createPosition(101, 4, 26),
|
||||||
|
createPosition(101, 20, 10),
|
||||||
|
createPosition(105, 4, 25),
|
||||||
|
createPosition(105, 20, 9),
|
||||||
|
createPosition(110, 4, 32),
|
||||||
|
createPosition(110, 20, 16),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFunctionInvocationHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.FUNCTION_INVOCATION);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(29, 8, 19),
|
||||||
|
createPosition(30, 8, 10),
|
||||||
|
createPosition(111, 22, 9),
|
||||||
|
createPosition(113, 21, 8),
|
||||||
|
createPosition(115, 4, 15),
|
||||||
|
createPosition(117, 4, 17),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void testGlobalVariableHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.GLOBAL_VARIABLE);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(7, 10, 14),
|
||||||
|
createPosition(8, 4, 14),
|
||||||
|
createPosition(9, 11, 20),
|
||||||
|
createPosition(96, 8, 14),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testMacroSubstitutionHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.MACRO_SUBSTITUTION);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(29, 8, 19),
|
||||||
|
createPosition(117, 4, 17),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTypedefHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.TYPEDEF);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(38, 21, 10),
|
||||||
|
createPosition(53, 22, 11),
|
||||||
|
createPosition(68, 22, 11),
|
||||||
|
createPosition(93, 17, 6),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testNamespaceHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.NAMESPACE);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(95, 10, 2),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testLabelHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.LABEL);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(116, 0, 5),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testEnumeratorHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.ENUMERATOR);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(4, 4, 10),
|
||||||
|
createPosition(34, 25, 13),
|
||||||
|
createPosition(49, 26, 14),
|
||||||
|
createPosition(64, 26, 14),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testProblemHighlighting() throws Exception {
|
||||||
|
setUpSemanticHighlighting(SemanticHighlightings.PROBLEM);
|
||||||
|
Position[] actual= getSemanticHighlightingPositions();
|
||||||
|
Position[] expected= new Position[] {
|
||||||
|
createPosition(73, 9, 2),
|
||||||
|
createPosition(73, 12, 2),
|
||||||
|
createPosition(74, 4, 2),
|
||||||
|
createPosition(75, 4, 2),
|
||||||
|
createPosition(76, 18, 2),
|
||||||
|
createPosition(76, 27, 2),
|
||||||
|
createPosition(82, 9, 2),
|
||||||
|
createPosition(82, 60, 2),
|
||||||
|
};
|
||||||
|
// System.out.println(toString(actual));
|
||||||
|
assertEqualPositions(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,3 +3,8 @@ org.eclipse.cdt.ui/debug=true
|
||||||
# Reports contentAssist activity
|
# Reports contentAssist activity
|
||||||
org.eclipse.cdt.ui/debug/contentassist=false
|
org.eclipse.cdt.ui/debug/contentassist=false
|
||||||
|
|
||||||
|
# Prints debug information related to the AST provider
|
||||||
|
org.eclipse.cdt.ui/debug/ASTProvider=false
|
||||||
|
|
||||||
|
# Enables all semantic highlighting types
|
||||||
|
org.eclipse.cdt.ui/debug/SemanticHighlighting=false
|
||||||
|
|
|
@ -621,12 +621,12 @@
|
||||||
class="org.eclipse.cdt.internal.ui.preferences.IndexerPreferencePage"
|
class="org.eclipse.cdt.internal.ui.preferences.IndexerPreferencePage"
|
||||||
id="org.eclipse.cdt.ui.preferences.IndexerPreferencePage"
|
id="org.eclipse.cdt.ui.preferences.IndexerPreferencePage"
|
||||||
name="%indexerPrefName"/>
|
name="%indexerPrefName"/>
|
||||||
<!--page
|
<page
|
||||||
name="%WorkInProgress.name"
|
name="%WorkInProgress.name"
|
||||||
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
|
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
|
||||||
class="org.eclipse.cdt.internal.ui.preferences.WorkInProgressPreferencePage"
|
class="org.eclipse.cdt.internal.ui.preferences.WorkInProgressPreferencePage"
|
||||||
id="org.eclipse.cdt.ui.preferneces.WorkInProgressPreferencePage">
|
id="org.eclipse.cdt.ui.preferneces.WorkInProgressPreferencePage">
|
||||||
</page-->
|
</page>
|
||||||
</extension>
|
</extension>
|
||||||
<extension
|
<extension
|
||||||
point="org.eclipse.ui.editorActions">
|
point="org.eclipse.ui.editorActions">
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2006 Wind River Systems, Inc. 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:
|
||||||
|
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.corext.util;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.DocumentEvent;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IPositionUpdater;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.core.PositionTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple general purpose position tracker.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SimplePositionTracker extends PositionTracker implements
|
||||||
|
IPositionUpdater {
|
||||||
|
|
||||||
|
private IDocument fDocument;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
|
||||||
|
*/
|
||||||
|
public void update(DocumentEvent event) {
|
||||||
|
String text = event.getText();
|
||||||
|
int insertLen = text != null ? text.length() : 0;
|
||||||
|
update(event.getOffset(), event.getLength(), insertLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update(int offset, int deleteLen, int insertLen) {
|
||||||
|
if (insertLen > deleteLen) {
|
||||||
|
insert(offset + deleteLen, insertLen - deleteLen);
|
||||||
|
} else if (insertLen < deleteLen) {
|
||||||
|
delete(offset+insertLen, deleteLen - insertLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start tracking on the given document.
|
||||||
|
*
|
||||||
|
* @param doc
|
||||||
|
*/
|
||||||
|
public synchronized void startTracking(IDocument doc) {
|
||||||
|
stopTracking();
|
||||||
|
fDocument= doc;
|
||||||
|
if (fDocument != null) {
|
||||||
|
fDocument.addPositionUpdater(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop tracking.
|
||||||
|
*/
|
||||||
|
public synchronized void stopTracking() {
|
||||||
|
if (fDocument != null) {
|
||||||
|
fDocument.removePositionUpdater(this);
|
||||||
|
fDocument= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy the tracker.
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
stopTracking();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -127,7 +127,7 @@ public class LineBackgroundPainter implements IPainter, LineBackgroundListener {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set highlight positions. It is assumed that all positions
|
* Set highlight positions. It is assumed that all positions
|
||||||
* are up-to-date with respect to the text viewers document.
|
* are up-to-date with respect to the text viewer document.
|
||||||
*
|
*
|
||||||
* @param positions a list of <code>Position</code>s
|
* @param positions a list of <code>Position</code>s
|
||||||
*/
|
*/
|
||||||
|
@ -142,6 +142,51 @@ public class LineBackgroundPainter implements IPainter, LineBackgroundListener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add highlight positions. It is assumed that all positions
|
||||||
|
* are up-to-date with respect to the text viewer document.
|
||||||
|
*
|
||||||
|
* @param positions a list of <code>Position</code>s
|
||||||
|
*/
|
||||||
|
public void addHighlightPositions(List positions) {
|
||||||
|
boolean isActive= fIsActive;
|
||||||
|
deactivate(isActive);
|
||||||
|
fPositions.addAll(positions);
|
||||||
|
if (isActive) {
|
||||||
|
activate(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove highlight positions by identity.
|
||||||
|
*
|
||||||
|
* @param positions a list of <code>Position</code>s
|
||||||
|
*/
|
||||||
|
public void removeHighlightPositions(List positions) {
|
||||||
|
boolean isActive= fIsActive;
|
||||||
|
deactivate(isActive);
|
||||||
|
fPositions.removeAll(positions);
|
||||||
|
if (isActive) {
|
||||||
|
activate(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace given highlight positions in one step.
|
||||||
|
*
|
||||||
|
* @param removePositions a list of <code>Position</code>s to remove
|
||||||
|
* @param addPositions a list of <code>Position</code>s to add
|
||||||
|
*/
|
||||||
|
public void replaceHighlightPositions(List removePositions, List addPositions) {
|
||||||
|
boolean isActive= fIsActive;
|
||||||
|
deactivate(isActive);
|
||||||
|
fPositions.removeAll(removePositions);
|
||||||
|
fPositions.addAll(addPositions);
|
||||||
|
if (isActive) {
|
||||||
|
activate(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger redraw of managed positions.
|
* Trigger redraw of managed positions.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,640 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.ISafeRunnable;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.OperationCanceledException;
|
||||||
|
import org.eclipse.core.runtime.Platform;
|
||||||
|
import org.eclipse.core.runtime.SafeRunner;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.jface.text.Assert;
|
||||||
|
import org.eclipse.ui.IPartListener2;
|
||||||
|
import org.eclipse.ui.IWindowListener;
|
||||||
|
import org.eclipse.ui.IWorkbenchPart;
|
||||||
|
import org.eclipse.ui.IWorkbenchPartReference;
|
||||||
|
import org.eclipse.ui.IWorkbenchWindow;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ILanguage;
|
||||||
|
import org.eclipse.cdt.core.model.ISourceReference;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a shared AST for clients. The shared AST is
|
||||||
|
* the AST of the active CEditor's input element.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public final class ASTProvider {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait flag.
|
||||||
|
*/
|
||||||
|
public static final class WAIT_FLAG {
|
||||||
|
|
||||||
|
String fName;
|
||||||
|
|
||||||
|
private WAIT_FLAG(String name) {
|
||||||
|
fName= name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see java.lang.Object#toString()
|
||||||
|
*/
|
||||||
|
public String toString() {
|
||||||
|
return fName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait flag indicating that a client requesting an AST
|
||||||
|
* wants to wait until an AST is ready.
|
||||||
|
* <p>
|
||||||
|
* An AST will be created by this AST provider if the shared
|
||||||
|
* AST is not for the given C element.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static final WAIT_FLAG WAIT_YES= new WAIT_FLAG("wait yes"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait flag indicating that a client requesting an AST
|
||||||
|
* only wants to wait for the shared AST of the active editor.
|
||||||
|
* <p>
|
||||||
|
* No AST will be created by the AST provider.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static final WAIT_FLAG WAIT_ACTIVE_ONLY= new WAIT_FLAG("wait active only"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait flag indicating that a client requesting an AST
|
||||||
|
* only wants the already available shared AST.
|
||||||
|
* <p>
|
||||||
|
* No AST will be created by the AST provider.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public static final WAIT_FLAG WAIT_NO= new WAIT_FLAG("don't wait"); //$NON-NLS-1$
|
||||||
|
|
||||||
|
public static int PARSE_MODE_FULL= ILanguage.AST_SKIP_IF_NO_BUILD_INFO;
|
||||||
|
public static int PARSE_MODE_FAST= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS;
|
||||||
|
public static int PARSE_MODE_FAST_INDEX= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS | ILanguage.AST_USE_INDEX;
|
||||||
|
public static int PARSE_MODE_INDEX= ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_USE_INDEX;
|
||||||
|
|
||||||
|
public static int PARSE_MODE= PARSE_MODE_FULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether this class is in debug mode.
|
||||||
|
*/
|
||||||
|
private static final boolean DEBUG= "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.cdt.ui/debug/ASTProvider")); //$NON-NLS-1$//$NON-NLS-2$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal activation listener.
|
||||||
|
*/
|
||||||
|
private class ActivationListener implements IPartListener2, IWindowListener {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partActivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partActivated(IWorkbenchPartReference ref) {
|
||||||
|
if (isCEditor(ref) && !isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partBroughtToTop(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partBroughtToTop(IWorkbenchPartReference ref) {
|
||||||
|
if (isCEditor(ref) && !isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partClosed(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partClosed(IWorkbenchPartReference ref) {
|
||||||
|
if (isActiveEditor(ref)) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "closed active editor: " + ref.getTitle()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
activeEditorChanged(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partDeactivated(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partDeactivated(IWorkbenchPartReference ref) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partOpened(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partOpened(IWorkbenchPartReference ref) {
|
||||||
|
if (isCEditor(ref) && !isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partHidden(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partHidden(IWorkbenchPartReference ref) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partVisible(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partVisible(IWorkbenchPartReference ref) {
|
||||||
|
if (isCEditor(ref) && !isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IPartListener2#partInputChanged(org.eclipse.ui.IWorkbenchPartReference)
|
||||||
|
*/
|
||||||
|
public void partInputChanged(IWorkbenchPartReference ref) {
|
||||||
|
if (isCEditor(ref) && isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
|
||||||
|
*/
|
||||||
|
public void windowActivated(IWorkbenchWindow window) {
|
||||||
|
IWorkbenchPartReference ref= window.getPartService().getActivePartReference();
|
||||||
|
if (isCEditor(ref) && !isActiveEditor(ref))
|
||||||
|
activeEditorChanged(ref.getPart(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWindowListener#windowDeactivated(org.eclipse.ui.IWorkbenchWindow)
|
||||||
|
*/
|
||||||
|
public void windowDeactivated(IWorkbenchWindow window) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWindowListener#windowClosed(org.eclipse.ui.IWorkbenchWindow)
|
||||||
|
*/
|
||||||
|
public void windowClosed(IWorkbenchWindow window) {
|
||||||
|
if (fActiveEditor != null && fActiveEditor.getSite() != null && window == fActiveEditor.getSite().getWorkbenchWindow()) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "closed active editor: " + fActiveEditor.getTitle()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
activeEditorChanged(null);
|
||||||
|
}
|
||||||
|
window.getPartService().removePartListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWindowListener#windowOpened(org.eclipse.ui.IWorkbenchWindow)
|
||||||
|
*/
|
||||||
|
public void windowOpened(IWorkbenchWindow window) {
|
||||||
|
window.getPartService().addPartListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActiveEditor(IWorkbenchPartReference ref) {
|
||||||
|
return ref != null && isActiveEditor(ref.getPart(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isActiveEditor(IWorkbenchPart part) {
|
||||||
|
return part != null && (part == fActiveEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isCEditor(IWorkbenchPartReference ref) {
|
||||||
|
if (ref == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String id= ref.getId();
|
||||||
|
|
||||||
|
return CUIPlugin.EDITOR_ID.equals(id) || ref.getPart(false) instanceof CEditor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String DEBUG_PREFIX= "ASTProvider > "; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
|
private ICElement fReconcilingCElement;
|
||||||
|
private ICElement fActiveCElement;
|
||||||
|
private IASTTranslationUnit fAST;
|
||||||
|
private ActivationListener fActivationListener;
|
||||||
|
private Object fReconcileLock= new Object();
|
||||||
|
private Object fWaitLock= new Object();
|
||||||
|
private boolean fIsReconciling;
|
||||||
|
private IWorkbenchPart fActiveEditor;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the C plug-in's AST provider.
|
||||||
|
*
|
||||||
|
* @return the AST provider
|
||||||
|
*/
|
||||||
|
public static ASTProvider getASTProvider() {
|
||||||
|
return CUIPlugin.getDefault().getASTProvider();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new AST provider.
|
||||||
|
*/
|
||||||
|
public ASTProvider() {
|
||||||
|
install();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs this AST provider.
|
||||||
|
*/
|
||||||
|
void install() {
|
||||||
|
// Create and register activation listener
|
||||||
|
fActivationListener= new ActivationListener();
|
||||||
|
PlatformUI.getWorkbench().addWindowListener(fActivationListener);
|
||||||
|
|
||||||
|
// Ensure existing windows get connected
|
||||||
|
IWorkbenchWindow[] windows= PlatformUI.getWorkbench().getWorkbenchWindows();
|
||||||
|
for (int i= 0, length= windows.length; i < length; i++)
|
||||||
|
windows[i].getPartService().addPartListener(fActivationListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void activeEditorChanged(IWorkbenchPart editor) {
|
||||||
|
|
||||||
|
ICElement cElement= null;
|
||||||
|
if (editor instanceof CEditor) {
|
||||||
|
cElement= ((CEditor)editor).getInputCElement();
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (this) {
|
||||||
|
fActiveEditor= editor;
|
||||||
|
fActiveCElement= cElement;
|
||||||
|
cache(null, cElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "active editor is: " + toString(cElement)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
if (fIsReconciling && (fReconcilingCElement == null || !fReconcilingCElement.equals(cElement))) {
|
||||||
|
fIsReconciling= false;
|
||||||
|
fReconcilingCElement= null;
|
||||||
|
} else if (cElement == null) {
|
||||||
|
fIsReconciling= false;
|
||||||
|
fReconcilingCElement= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the given translation unit AST is
|
||||||
|
* cached by this AST provided.
|
||||||
|
*
|
||||||
|
* @param ast the translation unit AST
|
||||||
|
* @return <code>true</code> if the given AST is the cached one
|
||||||
|
*/
|
||||||
|
public boolean isCached(IASTTranslationUnit ast) {
|
||||||
|
return ast != null && fAST == ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this AST provider is active on the given
|
||||||
|
* translation unit.
|
||||||
|
*
|
||||||
|
* @param tu the translation unit
|
||||||
|
* @return <code>true</code> if the given translation unit is the active one
|
||||||
|
*/
|
||||||
|
public boolean isActive(ITranslationUnit tu) {
|
||||||
|
return tu != null && tu.equals(fActiveCElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Informs that reconciling for the given element is about to be started.
|
||||||
|
*
|
||||||
|
* @param cElement the C element
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled()
|
||||||
|
*/
|
||||||
|
void aboutToBeReconciled(ICElement cElement) {
|
||||||
|
|
||||||
|
if (cElement == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "about to reconcile: " + toString(cElement)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
fIsReconciling= true;
|
||||||
|
fReconcilingCElement= cElement;
|
||||||
|
}
|
||||||
|
cache(null, cElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes the cached AST.
|
||||||
|
*/
|
||||||
|
private synchronized void disposeAST() {
|
||||||
|
|
||||||
|
if (fAST == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "disposing AST: " + toString(fAST) + " for: " + toString(fActiveCElement)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
|
||||||
|
fAST= null;
|
||||||
|
|
||||||
|
cache(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string for the given C element used for debugging.
|
||||||
|
*
|
||||||
|
* @param cElement the translation unit AST
|
||||||
|
* @return a string used for debugging
|
||||||
|
*/
|
||||||
|
private String toString(ICElement cElement) {
|
||||||
|
if (cElement == null)
|
||||||
|
return "null"; //$NON-NLS-1$
|
||||||
|
else
|
||||||
|
return cElement.getElementName();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a string for the given AST used for debugging.
|
||||||
|
*
|
||||||
|
* @param ast the translation unit AST
|
||||||
|
* @return a string used for debugging
|
||||||
|
*/
|
||||||
|
private String toString(IASTTranslationUnit ast) {
|
||||||
|
if (ast == null)
|
||||||
|
return "null"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
IASTNode[] nodes= ast.getDeclarations();
|
||||||
|
if (nodes != null && nodes.length > 0)
|
||||||
|
return nodes[0].getRawSignature();
|
||||||
|
else
|
||||||
|
return "AST without any declaration"; //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Caches the given translation unit AST for the given C element.
|
||||||
|
*
|
||||||
|
* @param ast
|
||||||
|
* @param cElement
|
||||||
|
*/
|
||||||
|
private synchronized void cache(IASTTranslationUnit ast, ICElement cElement) {
|
||||||
|
|
||||||
|
if (fActiveCElement != null && !fActiveCElement.equals(cElement)) {
|
||||||
|
if (DEBUG && cElement != null) // don't report call from disposeAST()
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "don't cache AST for inactive: " + toString(cElement)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DEBUG && (cElement != null || ast != null)) // don't report call from disposeAST()
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "caching AST: " + toString(ast) + " for: " + toString(cElement)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
|
||||||
|
if (fAST != null)
|
||||||
|
disposeAST();
|
||||||
|
|
||||||
|
fAST= ast;
|
||||||
|
|
||||||
|
// Signal AST change
|
||||||
|
synchronized (fWaitLock) {
|
||||||
|
fWaitLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a shared translation unit AST for the given
|
||||||
|
* C element.
|
||||||
|
* <p>
|
||||||
|
* Clients are not allowed to modify the AST and must
|
||||||
|
* synchronize all access to its nodes.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param cElement the C element
|
||||||
|
* @param waitFlag {@link #WAIT_YES}, {@link #WAIT_NO} or {@link #WAIT_ACTIVE_ONLY}
|
||||||
|
* @param progressMonitor the progress monitor or <code>null</code>
|
||||||
|
* @return the AST or <code>null</code> if the AST is not available
|
||||||
|
*/
|
||||||
|
public IASTTranslationUnit getAST(ICElement cElement, WAIT_FLAG waitFlag, IProgressMonitor progressMonitor) {
|
||||||
|
if (cElement == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Assert.isTrue(cElement instanceof ITranslationUnit);
|
||||||
|
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
boolean isActiveElement;
|
||||||
|
synchronized (this) {
|
||||||
|
isActiveElement= cElement.equals(fActiveCElement);
|
||||||
|
if (isActiveElement) {
|
||||||
|
if (fAST != null) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "returning cached AST:" + toString(fAST) + " for: " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
|
||||||
|
return fAST;
|
||||||
|
}
|
||||||
|
if (waitFlag == WAIT_NO) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "returning null (WAIT_NO) for: " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isActiveElement && isReconciling(cElement)) {
|
||||||
|
try {
|
||||||
|
final ICElement activeElement= fReconcilingCElement;
|
||||||
|
|
||||||
|
// Wait for AST
|
||||||
|
synchronized (fWaitLock) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "waiting for AST for: " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
fWaitLock.wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check whether active element is still valid
|
||||||
|
synchronized (this) {
|
||||||
|
if (activeElement == fActiveCElement && fAST != null) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "...got AST for: " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
return fAST;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getAST(cElement, waitFlag, progressMonitor);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return null; // thread has been interrupted don't compute AST
|
||||||
|
}
|
||||||
|
} else if (waitFlag == WAIT_NO || (waitFlag == WAIT_ACTIVE_ONLY && !(isActiveElement && fAST == null)))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (isActiveElement)
|
||||||
|
aboutToBeReconciled(cElement);
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.err.println(getThreadName() + " - " + DEBUG_PREFIX + "creating AST for " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
IASTTranslationUnit ast= null;
|
||||||
|
try {
|
||||||
|
ast= createAST(cElement, progressMonitor);
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled())
|
||||||
|
ast= null;
|
||||||
|
else if (DEBUG && ast != null)
|
||||||
|
System.err.println(getThreadName() + " - " + DEBUG_PREFIX + "created AST for: " + cElement.getElementName()); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
} finally {
|
||||||
|
if (isActiveElement) {
|
||||||
|
if (fAST != null) {
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "Ignore created AST for " + cElement.getElementName() + "- AST from reconciler is newer"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
reconciled(fAST, cElement, null);
|
||||||
|
} else
|
||||||
|
reconciled(ast, cElement, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells whether the given C element is the one
|
||||||
|
* reported as currently being reconciled.
|
||||||
|
*
|
||||||
|
* @param cElement the C element
|
||||||
|
* @return <code>true</code> if reported as currently being reconciled
|
||||||
|
*/
|
||||||
|
private boolean isReconciling(ICElement cElement) {
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
return cElement != null && cElement.equals(fReconcilingCElement) && fIsReconciling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new translation unit AST.
|
||||||
|
*
|
||||||
|
* @param cElement the C element for which to create the AST
|
||||||
|
* @param progressMonitor the progress monitor
|
||||||
|
* @return AST
|
||||||
|
*/
|
||||||
|
IASTTranslationUnit createAST(ICElement cElement, final IProgressMonitor progressMonitor) {
|
||||||
|
if (!hasSource(cElement))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!(cElement instanceof ITranslationUnit))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
final ITranslationUnit tu= (ITranslationUnit)cElement;
|
||||||
|
final IASTTranslationUnit root[]= new IASTTranslationUnit[1];
|
||||||
|
|
||||||
|
SafeRunner.run(new ISafeRunnable() {
|
||||||
|
public void run() throws CoreException {
|
||||||
|
try {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) {
|
||||||
|
root[0]= null;
|
||||||
|
} else {
|
||||||
|
root[0]= tu.getLanguage().getASTTranslationUnit(tu, PARSE_MODE);
|
||||||
|
}
|
||||||
|
} catch (OperationCanceledException ex) {
|
||||||
|
root[0]= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void handleException(Throwable ex) {
|
||||||
|
IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, "Error in CDT Core during AST creation", ex); //$NON-NLS-1$
|
||||||
|
CUIPlugin.getDefault().getLog().log(status);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return root[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the given C element has accessible source.
|
||||||
|
*
|
||||||
|
* @param cElement the C element to test
|
||||||
|
* @return <code>true</code> if the element has source
|
||||||
|
*/
|
||||||
|
private boolean hasSource(ICElement cElement) {
|
||||||
|
if (cElement == null || !cElement.exists())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return cElement instanceof ISourceReference /* && ((ISourceReference)cElement).getSource() != null */;
|
||||||
|
} catch (Exception ex) {
|
||||||
|
IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, "Error in CDT Core during AST creation", ex); //$NON-NLS-1$
|
||||||
|
CUIPlugin.getDefault().getLog().log(status);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disposes this AST provider.
|
||||||
|
*/
|
||||||
|
public void dispose() {
|
||||||
|
|
||||||
|
// Dispose activation listener
|
||||||
|
PlatformUI.getWorkbench().removeWindowListener(fActivationListener);
|
||||||
|
fActivationListener= null;
|
||||||
|
|
||||||
|
disposeAST();
|
||||||
|
|
||||||
|
synchronized (fWaitLock) {
|
||||||
|
fWaitLock.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(org.eclipse.cdt.core.dom.IASTTranslationUnit)
|
||||||
|
*/
|
||||||
|
void reconciled(IASTTranslationUnit ast, ICElement cElement, IProgressMonitor progressMonitor) {
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + "reconciled: " + toString(cElement) + ", AST: " + toString(ast)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
|
||||||
|
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
|
||||||
|
fIsReconciling= progressMonitor != null && progressMonitor.isCanceled();
|
||||||
|
if (cElement == null || !cElement.equals(fReconcilingCElement)) {
|
||||||
|
|
||||||
|
if (DEBUG)
|
||||||
|
System.out.println(getThreadName() + " - " + DEBUG_PREFIX + " ignoring AST of out-dated editor"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||||
|
|
||||||
|
// Signal - threads might wait for wrong element
|
||||||
|
synchronized (fWaitLock) {
|
||||||
|
fWaitLock.notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache(ast, cElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getThreadName() {
|
||||||
|
String name= Thread.currentThread().getName();
|
||||||
|
if (name != null)
|
||||||
|
return name;
|
||||||
|
else
|
||||||
|
return Thread.currentThread().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -21,6 +21,8 @@ import java.util.ResourceBundle;
|
||||||
|
|
||||||
import org.eclipse.core.resources.IFile;
|
import org.eclipse.core.resources.IFile;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.ListenerList;
|
||||||
import org.eclipse.core.runtime.content.IContentType;
|
import org.eclipse.core.runtime.content.IContentType;
|
||||||
import org.eclipse.jface.action.Action;
|
import org.eclipse.jface.action.Action;
|
||||||
import org.eclipse.jface.action.IAction;
|
import org.eclipse.jface.action.IAction;
|
||||||
|
@ -119,6 +121,8 @@ import com.ibm.icu.text.BreakIterator;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
import org.eclipse.cdt.core.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.CCorePreferenceConstants;
|
import org.eclipse.cdt.core.CCorePreferenceConstants;
|
||||||
|
import org.eclipse.cdt.core.IPositionConverter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.model.CModelException;
|
import org.eclipse.cdt.core.model.CModelException;
|
||||||
import org.eclipse.cdt.core.model.ICElement;
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
import org.eclipse.cdt.core.model.ISourceRange;
|
import org.eclipse.cdt.core.model.ISourceRange;
|
||||||
|
@ -132,6 +136,8 @@ import org.eclipse.cdt.ui.actions.ShowInCViewAction;
|
||||||
import org.eclipse.cdt.ui.text.ICPartitions;
|
import org.eclipse.cdt.ui.text.ICPartitions;
|
||||||
import org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider;
|
import org.eclipse.cdt.ui.text.folding.ICFoldingStructureProvider;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.corext.util.SimplePositionTracker;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
||||||
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
||||||
import org.eclipse.cdt.internal.ui.actions.AddBlockCommentAction;
|
import org.eclipse.cdt.internal.ui.actions.AddBlockCommentAction;
|
||||||
|
@ -150,6 +156,7 @@ import org.eclipse.cdt.internal.ui.text.CTextTools;
|
||||||
import org.eclipse.cdt.internal.ui.text.CWordIterator;
|
import org.eclipse.cdt.internal.ui.text.CWordIterator;
|
||||||
import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator;
|
import org.eclipse.cdt.internal.ui.text.DocumentCharacterIterator;
|
||||||
import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter;
|
import org.eclipse.cdt.internal.ui.text.HTMLTextPresenter;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.ICReconcilingListener;
|
||||||
import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl;
|
import org.eclipse.cdt.internal.ui.text.c.hover.SourceViewerInformationControl;
|
||||||
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
|
import org.eclipse.cdt.internal.ui.text.contentassist.ContentAssistPreference;
|
||||||
import org.eclipse.cdt.internal.ui.util.CUIHelp;
|
import org.eclipse.cdt.internal.ui.util.CUIHelp;
|
||||||
|
@ -158,9 +165,8 @@ import org.eclipse.cdt.internal.ui.util.CUIHelp;
|
||||||
/**
|
/**
|
||||||
* C specific text editor.
|
* C specific text editor.
|
||||||
*/
|
*/
|
||||||
public class CEditor extends TextEditor implements ISelectionChangedListener, IShowInSource , IReconcilingParticipant{
|
public class CEditor extends TextEditor implements ISelectionChangedListener, IShowInSource, IReconcilingParticipant, ICReconcilingListener {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The information provider used to present focusable information
|
* The information provider used to present focusable information
|
||||||
* shells.
|
* shells.
|
||||||
|
@ -554,6 +560,19 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
*/
|
*/
|
||||||
private FoldingActionGroup fFoldingGroup;
|
private FoldingActionGroup fFoldingGroup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AST reconciling listeners.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private ListenerList fReconcilingListeners= new ListenerList(ListenerList.IDENTITY);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting manager
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private SemanticHighlightingManager fSemanticManager;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor.
|
* Default constructor.
|
||||||
*/
|
*/
|
||||||
|
@ -590,11 +609,6 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
if (fCEditorErrorTickUpdater != null) {
|
if (fCEditorErrorTickUpdater != null) {
|
||||||
fCEditorErrorTickUpdater.updateEditorImage(getInputCElement());
|
fCEditorErrorTickUpdater.updateEditorImage(getInputCElement());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getSourceViewer() != null) {
|
|
||||||
CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(getSourceViewer());
|
|
||||||
decoSupport.editorInputChanged(input);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -732,6 +746,16 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SemanticHighlightings.affectsEnablement(getPreferenceStore(), event)) {
|
||||||
|
if (isSemanticHighlightingEnabled()) {
|
||||||
|
installSemanticHighlighting();
|
||||||
|
fSemanticManager.refresh();
|
||||||
|
} else {
|
||||||
|
uninstallSemanticHighlighting();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
IContentAssistant c= asv.getContentAssistant();
|
IContentAssistant c= asv.getContentAssistant();
|
||||||
if (c instanceof ContentAssistant) {
|
if (c instanceof ContentAssistant) {
|
||||||
ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
|
ContentAssistPreference.changeConfiguration((ContentAssistant) c, getPreferenceStore(), event);
|
||||||
|
@ -1211,7 +1235,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
|
|
||||||
if (isTabConversionEnabled())
|
if (isTabConversionEnabled())
|
||||||
startTabConversion();
|
startTabConversion();
|
||||||
|
|
||||||
|
if (isSemanticHighlightingEnabled())
|
||||||
|
installSemanticHighlighting();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1234,12 +1261,12 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#getSourceViewerDecorationSupport(org.eclipse.jface.text.source.ISourceViewer)
|
* @see org.eclipse.ui.texteditor.AbstractDecoratedTextEditor#getSourceViewerDecorationSupport(ISourceViewer)
|
||||||
*/
|
*/
|
||||||
protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(
|
protected SourceViewerDecorationSupport getSourceViewerDecorationSupport(
|
||||||
ISourceViewer viewer) {
|
ISourceViewer viewer) {
|
||||||
if (fSourceViewerDecorationSupport == null) {
|
if (fSourceViewerDecorationSupport == null) {
|
||||||
fSourceViewerDecorationSupport= new CSourceViewerDecorationSupport(viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors());
|
fSourceViewerDecorationSupport= new CSourceViewerDecorationSupport(this, viewer, getOverviewRuler(), getAnnotationAccess(), getSharedColors());
|
||||||
configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
|
configureSourceViewerDecorationSupport(fSourceViewerDecorationSupport);
|
||||||
}
|
}
|
||||||
return fSourceViewerDecorationSupport;
|
return fSourceViewerDecorationSupport;
|
||||||
|
@ -1557,11 +1584,10 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
getOverviewRuler(),
|
getOverviewRuler(),
|
||||||
isOverviewRulerVisible());
|
isOverviewRulerVisible());
|
||||||
|
|
||||||
CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(sourceViewer);
|
|
||||||
decoSupport.editorInputChanged(getEditorInput());
|
|
||||||
|
|
||||||
CUIHelp.setHelp(this, sourceViewer.getTextWidget(), ICHelpContextIds.CEDITOR_VIEW);
|
CUIHelp.setHelp(this, sourceViewer.getTextWidget(), ICHelpContextIds.CEDITOR_VIEW);
|
||||||
|
|
||||||
|
getSourceViewerDecorationSupport(sourceViewer);
|
||||||
|
|
||||||
return sourceViewer;
|
return sourceViewer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1701,16 +1727,36 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/*
|
||||||
* @see org.eclipse.cdt.internal.ui.editor.IReconcilingParticipant#reconciled()
|
* @see org.eclipse.cdt.internal.ui.editor.IReconcilingParticipant#reconciled()
|
||||||
*/
|
*/
|
||||||
public void reconciled(boolean somethingHasChanged) {
|
public void reconciled(boolean somethingHasChanged) {
|
||||||
// Do nothing the outliner is listener to the
|
if (getSourceViewer() == null) {
|
||||||
// CoreModel WorkingCopy changes instead.
|
return;
|
||||||
// It will allow more fined grained.
|
}
|
||||||
if (somethingHasChanged && getSourceViewer() != null) {
|
// this method must be called in a background thread
|
||||||
CSourceViewerDecorationSupport decoSupport = (CSourceViewerDecorationSupport) getSourceViewerDecorationSupport(getSourceViewer());
|
assert getSourceViewer().getTextWidget().getDisplay().getThread() != Thread.currentThread();
|
||||||
decoSupport.editorInputChanged(getEditorInput());
|
|
||||||
|
if (fReconcilingListeners.size() > 0) {
|
||||||
|
// create AST and notify ICReconcilingListeners
|
||||||
|
ICElement cElement= getInputCElement();
|
||||||
|
if (cElement == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutToBeReconciled();
|
||||||
|
|
||||||
|
// track changes to the document while parsing
|
||||||
|
IDocument doc= getDocumentProvider().getDocument(getEditorInput());
|
||||||
|
SimplePositionTracker positionTracker= new SimplePositionTracker();
|
||||||
|
positionTracker.startTracking(doc);
|
||||||
|
|
||||||
|
try {
|
||||||
|
IASTTranslationUnit ast= CUIPlugin.getDefault().getASTProvider().createAST(cElement, null);
|
||||||
|
reconciled(ast, positionTracker, null);
|
||||||
|
} finally {
|
||||||
|
positionTracker.stopTracking();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2099,4 +2145,101 @@ public class CEditor extends TextEditor implements ISelectionChangedListener, IS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled()
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public void aboutToBeReconciled() {
|
||||||
|
|
||||||
|
// Notify AST provider
|
||||||
|
CUIPlugin.getDefault().getASTProvider().aboutToBeReconciled(getInputCElement());
|
||||||
|
|
||||||
|
// Notify listeners
|
||||||
|
Object[] listeners = fReconcilingListeners.getListeners();
|
||||||
|
for (int i = 0, length= listeners.length; i < length; ++i) {
|
||||||
|
((ICReconcilingListener)listeners[i]).aboutToBeReconciled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, IPositionConverter, IProgressMonitor)
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public void reconciled(IASTTranslationUnit ast, IPositionConverter positionTracker, IProgressMonitor progressMonitor) {
|
||||||
|
|
||||||
|
CUIPlugin cuiPlugin= CUIPlugin.getDefault();
|
||||||
|
if (cuiPlugin == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Always notify AST provider
|
||||||
|
cuiPlugin.getASTProvider().reconciled(ast, getInputCElement(), progressMonitor);
|
||||||
|
|
||||||
|
// Notify listeners
|
||||||
|
Object[] listeners = fReconcilingListeners.getListeners();
|
||||||
|
for (int i = 0, length= listeners.length; i < length; ++i) {
|
||||||
|
((ICReconcilingListener)listeners[i]).reconciled(ast, positionTracker, progressMonitor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given listener.
|
||||||
|
* Has no effect if an identical listener was not already registered.
|
||||||
|
*
|
||||||
|
* @param listener The reconcile listener to be added
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
final void addReconcileListener(ICReconcilingListener listener) {
|
||||||
|
synchronized (fReconcilingListeners) {
|
||||||
|
fReconcilingListeners.add(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the given listener.
|
||||||
|
* Has no effect if an identical listener was not already registered.
|
||||||
|
*
|
||||||
|
* @param listener the reconcile listener to be removed
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
final void removeReconcileListener(ICReconcilingListener listener) {
|
||||||
|
synchronized (fReconcilingListeners) {
|
||||||
|
fReconcilingListeners.remove(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if Semantic Highlighting is enabled.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private boolean isSemanticHighlightingEnabled() {
|
||||||
|
return SemanticHighlightings.isEnabled(getPreferenceStore());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install Semantic Highlighting.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private void installSemanticHighlighting() {
|
||||||
|
if (fSemanticManager == null) {
|
||||||
|
fSemanticManager= new SemanticHighlightingManager();
|
||||||
|
fSemanticManager.install(this, (CSourceViewer) getSourceViewer(), CUIPlugin.getDefault().getTextTools().getColorManager(), getPreferenceStore());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall Semantic Highlighting.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private void uninstallSemanticHighlighting() {
|
||||||
|
if (fSemanticManager != null) {
|
||||||
|
fSemanticManager.uninstall();
|
||||||
|
fSemanticManager= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#########################################
|
#########################################
|
||||||
# Copyright (c) 2005 IBM Corporation and others.
|
# Copyright (c) 2005, 2006 IBM Corporation and others.
|
||||||
# All rights reserved. This program and the accompanying materials
|
# All rights reserved. This program and the accompanying materials
|
||||||
# are made available under the terms of the Eclipse Public License v1.0
|
# are made available under the terms of the Eclipse Public License v1.0
|
||||||
# which accompanies this distribution, and is available at
|
# which accompanies this distribution, and is available at
|
||||||
|
@ -8,6 +8,7 @@
|
||||||
# Contributors:
|
# Contributors:
|
||||||
# IBM Corporation - initial API and implementation
|
# IBM Corporation - initial API and implementation
|
||||||
# QNX Software System
|
# QNX Software System
|
||||||
|
# Anton Leherbauer (Wind River Systems)
|
||||||
#########################################
|
#########################################
|
||||||
|
|
||||||
AddIncludeOnSelection.description=Add include statement on selection
|
AddIncludeOnSelection.description=Add include statement on selection
|
||||||
|
@ -201,3 +202,33 @@ ShowToolTip.label=Show T&ooltip Description
|
||||||
|
|
||||||
ToggleComment_error_title=Comment/Uncomment
|
ToggleComment_error_title=Comment/Uncomment
|
||||||
ToggleComment_error_message=An error occurred while commenting/uncommenting.
|
ToggleComment_error_message=An error occurred while commenting/uncommenting.
|
||||||
|
|
||||||
|
InactiveCodeHighlighting_job= Inactive Code Highlighting
|
||||||
|
|
||||||
|
Reconciling_job= Reconciling
|
||||||
|
|
||||||
|
SemanticHighlighting_job= Semantic Highlighting
|
||||||
|
SemanticHighlighting_field= Fields
|
||||||
|
SemanticHighlighting_staticField= Static fields
|
||||||
|
SemanticHighlighting_staticConstField= Constants
|
||||||
|
SemanticHighlighting_methodDeclaration= Method declarations
|
||||||
|
SemanticHighlighting_staticMethodInvocation= Static method invocations
|
||||||
|
SemanticHighlighting_virtualMethodInvocation= Virtual method invocations
|
||||||
|
SemanticHighlighting_inheritedMethodInvocation= Inherited method invocations
|
||||||
|
SemanticHighlighting_localVariableDeclaration= Local variable declarations
|
||||||
|
SemanticHighlighting_localVariable= Local variable references
|
||||||
|
SemanticHighlighting_globalVariable= Global variables
|
||||||
|
SemanticHighlighting_parameterVariable= Parameter variables
|
||||||
|
SemanticHighlighting_TemplateVariables= Template variables
|
||||||
|
SemanticHighlighting_method= Methods
|
||||||
|
SemanticHighlighting_classes= Classes
|
||||||
|
SemanticHighlighting_enums= Enums
|
||||||
|
SemanticHighlighting_templateArguments= Template arguments
|
||||||
|
SemanticHighlighting_functionDeclaration= Function declarations
|
||||||
|
SemanticHighlighting_functionInvocation= Function invocations
|
||||||
|
SemanticHighlighting_macroSubstitions= Macro references
|
||||||
|
SemanticHighlighting_macroDefintion= Macro definitions
|
||||||
|
SemanticHighlighting_typeDef= Typedefs
|
||||||
|
SemanticHighlighting_namespace= Namespaces
|
||||||
|
SemanticHighlighting_label= Labels
|
||||||
|
SemanticHighlighting_problem= Problems
|
||||||
|
|
|
@ -10,23 +10,9 @@
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.editor;
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.EmptyStackException;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.eclipse.core.runtime.CoreException;
|
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
|
||||||
import org.eclipse.core.runtime.IStatus;
|
|
||||||
import org.eclipse.core.runtime.Status;
|
|
||||||
import org.eclipse.core.runtime.jobs.Job;
|
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.preference.PreferenceConverter;
|
import org.eclipse.jface.preference.PreferenceConverter;
|
||||||
import org.eclipse.jface.text.IRegion;
|
|
||||||
import org.eclipse.jface.text.ITextViewerExtension2;
|
import org.eclipse.jface.text.ITextViewerExtension2;
|
||||||
import org.eclipse.jface.text.Position;
|
|
||||||
import org.eclipse.jface.text.source.IAnnotationAccess;
|
import org.eclipse.jface.text.source.IAnnotationAccess;
|
||||||
import org.eclipse.jface.text.source.IOverviewRuler;
|
import org.eclipse.jface.text.source.IOverviewRuler;
|
||||||
import org.eclipse.jface.text.source.ISharedTextColors;
|
import org.eclipse.jface.text.source.ISharedTextColors;
|
||||||
|
@ -34,24 +20,8 @@ import org.eclipse.jface.text.source.ISourceViewer;
|
||||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||||
import org.eclipse.swt.graphics.Color;
|
import org.eclipse.swt.graphics.Color;
|
||||||
import org.eclipse.swt.graphics.RGB;
|
import org.eclipse.swt.graphics.RGB;
|
||||||
import org.eclipse.ui.IEditorInput;
|
|
||||||
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
|
import org.eclipse.ui.texteditor.SourceViewerDecorationSupport;
|
||||||
|
|
||||||
import org.eclipse.cdt.core.CCorePlugin;
|
|
||||||
import org.eclipse.cdt.core.IPositionConverter;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
|
||||||
import org.eclipse.cdt.core.model.ILanguage;
|
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
|
||||||
import org.eclipse.cdt.ui.CUIPlugin;
|
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.LineBackgroundPainter;
|
import org.eclipse.cdt.internal.ui.LineBackgroundPainter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -64,69 +34,10 @@ import org.eclipse.cdt.internal.ui.LineBackgroundPainter;
|
||||||
*
|
*
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class CSourceViewerDecorationSupport
|
public class CSourceViewerDecorationSupport extends SourceViewerDecorationSupport {
|
||||||
extends SourceViewerDecorationSupport {
|
|
||||||
|
|
||||||
/**
|
/** The key to use for the {@link LineBackgroundPainter} */
|
||||||
* This job takes the current translation unit and produces an
|
private static final String INACTIVE_CODE_KEY = "inactiveCode"; //$NON-NLS-1$
|
||||||
* AST in the background. Upon completion, {@link #inactiveCodePositionsChanged}
|
|
||||||
* is called in the display thread.
|
|
||||||
*/
|
|
||||||
private class UpdateJob extends Job {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param name
|
|
||||||
*/
|
|
||||||
public UpdateJob(String name) {
|
|
||||||
super(name);
|
|
||||||
setSystem(true);
|
|
||||||
setPriority(Job.DECORATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
|
|
||||||
*/
|
|
||||||
protected IStatus run(IProgressMonitor monitor) {
|
|
||||||
IStatus result = Status.OK_STATUS;
|
|
||||||
if (fASTTranslationUnit == null && fTranslationUnit != null) {
|
|
||||||
try {
|
|
||||||
fParseTimeStamp = System.currentTimeMillis();
|
|
||||||
int style = ILanguage.AST_SKIP_IF_NO_BUILD_INFO | ILanguage.AST_SKIP_INDEXED_HEADERS;
|
|
||||||
fASTTranslationUnit = fTranslationUnit.getLanguage().getASTTranslationUnit(fTranslationUnit, style);
|
|
||||||
} catch (CoreException exc) {
|
|
||||||
result = exc.getStatus();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (monitor.isCanceled() || fViewer == null) {
|
|
||||||
result = Status.CANCEL_STATUS;
|
|
||||||
} else {
|
|
||||||
final List inactiveCodePositions = collectInactiveCodePositions(fASTTranslationUnit);
|
|
||||||
Runnable updater = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
inactiveCodePositionsChanged(inactiveCodePositions);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (fViewer != null && !monitor.isCanceled()) {
|
|
||||||
fViewer.getTextWidget().getDisplay().asyncExec(updater);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of <code>IRegion</code> that can be reused
|
|
||||||
* by setting the offset and the length.
|
|
||||||
*/
|
|
||||||
private static class ReusableRegion extends Position implements IRegion {
|
|
||||||
public ReusableRegion(int offset, int length) {
|
|
||||||
super(offset, length);
|
|
||||||
}
|
|
||||||
public ReusableRegion(IRegion region) {
|
|
||||||
super(region.getOffset(), region.getLength());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The preference key for the inactive code highlight color */
|
/** The preference key for the inactive code highlight color */
|
||||||
private String fInactiveCodeColorKey;
|
private String fInactiveCodeColorKey;
|
||||||
|
@ -144,14 +55,10 @@ public class CSourceViewerDecorationSupport
|
||||||
private String fCLPEnableKey;
|
private String fCLPEnableKey;
|
||||||
/** The source viewer (duplicate of private base class member) */
|
/** The source viewer (duplicate of private base class member) */
|
||||||
protected ISourceViewer fViewer;
|
protected ISourceViewer fViewer;
|
||||||
/** The current translation unit */
|
/** The editor we are associated with */
|
||||||
private ITranslationUnit fTranslationUnit;
|
private CEditor fEditor;
|
||||||
/** The corresponding AST translation unit */
|
/** The inactive code highlighting */
|
||||||
private IASTTranslationUnit fASTTranslationUnit;
|
private InactiveCodeHighlighting fInactiveCodeHighlighting;
|
||||||
/** The time stamp when the parsing was initiated */
|
|
||||||
private long fParseTimeStamp;
|
|
||||||
/** The background job doing the AST parsing */
|
|
||||||
private Job fUpdateJob;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inherited constructor.
|
* Inherited constructor.
|
||||||
|
@ -162,55 +69,22 @@ public class CSourceViewerDecorationSupport
|
||||||
* @param sharedTextColors
|
* @param sharedTextColors
|
||||||
*/
|
*/
|
||||||
CSourceViewerDecorationSupport(
|
CSourceViewerDecorationSupport(
|
||||||
|
CEditor editor,
|
||||||
ISourceViewer sourceViewer,
|
ISourceViewer sourceViewer,
|
||||||
IOverviewRuler overviewRuler,
|
IOverviewRuler overviewRuler,
|
||||||
IAnnotationAccess annotationAccess,
|
IAnnotationAccess annotationAccess,
|
||||||
ISharedTextColors sharedTextColors) {
|
ISharedTextColors sharedTextColors) {
|
||||||
super(sourceViewer, overviewRuler, annotationAccess, sharedTextColors);
|
super(sourceViewer, overviewRuler, annotationAccess, sharedTextColors);
|
||||||
// we have to save our own reference, because super class members are all private
|
fEditor = editor;
|
||||||
|
// we have to save our own references, because super class members are all private
|
||||||
fViewer = sourceViewer;
|
fViewer = sourceViewer;
|
||||||
fSharedColors = sharedTextColors;
|
fSharedColors = sharedTextColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify that the associated editor got a new input.
|
|
||||||
* This is currently also used to notify of a reconcilation
|
|
||||||
* to update the inactive code while editing.
|
|
||||||
*
|
|
||||||
* @param input the new editor input
|
|
||||||
*/
|
|
||||||
void editorInputChanged(IEditorInput input) {
|
|
||||||
if (fUpdateJob != null) {
|
|
||||||
fUpdateJob.cancel();
|
|
||||||
}
|
|
||||||
fTranslationUnit = CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(input);
|
|
||||||
fASTTranslationUnit = null;
|
|
||||||
if (isInactiveCodePositionsActive()) {
|
|
||||||
updateInactiveCodePositions();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Schedule update of the AST in the background.
|
|
||||||
*/
|
|
||||||
private void updateInactiveCodePositions() {
|
|
||||||
if (fUpdateJob == null) {
|
|
||||||
fUpdateJob = new UpdateJob("Update Inactive Code Positions"); //$NON-NLS-1$
|
|
||||||
}
|
|
||||||
if (fUpdateJob.getState() == Job.NONE) {
|
|
||||||
fUpdateJob.schedule();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#dispose()
|
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#dispose()
|
||||||
*/
|
*/
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
if (fUpdateJob != null) {
|
|
||||||
fUpdateJob.cancel();
|
|
||||||
}
|
|
||||||
fTranslationUnit = null;
|
|
||||||
fASTTranslationUnit = null;
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,7 +103,7 @@ public class CSourceViewerDecorationSupport
|
||||||
updateCLPColor();
|
updateCLPColor();
|
||||||
} else if (p.equals(fInactiveCodeEnableKey)) {
|
} else if (p.equals(fInactiveCodeEnableKey)) {
|
||||||
if (isInactiveCodePositionsActive()) {
|
if (isInactiveCodePositionsActive()) {
|
||||||
showInactiveCodePositions();
|
showInactiveCodePositions(true);
|
||||||
} else {
|
} else {
|
||||||
hideInactiveCodePositions();
|
hideInactiveCodePositions();
|
||||||
}
|
}
|
||||||
|
@ -244,7 +118,7 @@ public class CSourceViewerDecorationSupport
|
||||||
*/
|
*/
|
||||||
private void updateInactiveCodeColor() {
|
private void updateInactiveCodeColor() {
|
||||||
if (fLineBackgroundPainter != null) {
|
if (fLineBackgroundPainter != null) {
|
||||||
fLineBackgroundPainter.setDefaultColor(getColor(fInactiveCodeColorKey));
|
fLineBackgroundPainter.setBackgroundColor(INACTIVE_CODE_KEY, getColor(fInactiveCodeColorKey));
|
||||||
if (isInactiveCodePositionsActive()) {
|
if (isInactiveCodePositionsActive()) {
|
||||||
fLineBackgroundPainter.redraw();
|
fLineBackgroundPainter.redraw();
|
||||||
}
|
}
|
||||||
|
@ -342,7 +216,7 @@ public class CSourceViewerDecorationSupport
|
||||||
showCLP();
|
showCLP();
|
||||||
}
|
}
|
||||||
if (isInactiveCodePositionsActive()) {
|
if (isInactiveCodePositionsActive()) {
|
||||||
showInactiveCodePositions();
|
showInactiveCodePositions(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -350,6 +224,10 @@ public class CSourceViewerDecorationSupport
|
||||||
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#uninstall()
|
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#uninstall()
|
||||||
*/
|
*/
|
||||||
public void uninstall() {
|
public void uninstall() {
|
||||||
|
if (fInactiveCodeHighlighting != null) {
|
||||||
|
fInactiveCodeHighlighting.dispose();
|
||||||
|
fInactiveCodeHighlighting= null;
|
||||||
|
}
|
||||||
uninstallLineBackgroundPainter();
|
uninstallLineBackgroundPainter();
|
||||||
super.uninstall();
|
super.uninstall();
|
||||||
}
|
}
|
||||||
|
@ -361,7 +239,7 @@ public class CSourceViewerDecorationSupport
|
||||||
if (fLineBackgroundPainter == null) {
|
if (fLineBackgroundPainter == null) {
|
||||||
if (fViewer instanceof ITextViewerExtension2) {
|
if (fViewer instanceof ITextViewerExtension2) {
|
||||||
fLineBackgroundPainter = new LineBackgroundPainter(fViewer);
|
fLineBackgroundPainter = new LineBackgroundPainter(fViewer);
|
||||||
fLineBackgroundPainter.setDefaultColor(getColor(fInactiveCodeColorKey));
|
fLineBackgroundPainter.setBackgroundColor(INACTIVE_CODE_KEY, getColor(fInactiveCodeColorKey));
|
||||||
fLineBackgroundPainter.setCursorLineColor(getColor(fCLPColorKey));
|
fLineBackgroundPainter.setCursorLineColor(getColor(fCLPColorKey));
|
||||||
fLineBackgroundPainter.enableCursorLine(isCLPActive());
|
fLineBackgroundPainter.enableCursorLine(isCLPActive());
|
||||||
((ITextViewerExtension2)fViewer).addPainter(fLineBackgroundPainter);
|
((ITextViewerExtension2)fViewer).addPainter(fLineBackgroundPainter);
|
||||||
|
@ -385,10 +263,18 @@ public class CSourceViewerDecorationSupport
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show inactive code positions.
|
* Show inactive code positions.
|
||||||
|
*
|
||||||
|
* @param refresh trigger a refresh of the positions
|
||||||
*/
|
*/
|
||||||
private void showInactiveCodePositions() {
|
private void showInactiveCodePositions(boolean refresh) {
|
||||||
installLineBackgroundPainter();
|
installLineBackgroundPainter();
|
||||||
updateInactiveCodePositions();
|
if (fLineBackgroundPainter != null) {
|
||||||
|
fInactiveCodeHighlighting= new InactiveCodeHighlighting(fLineBackgroundPainter, INACTIVE_CODE_KEY);
|
||||||
|
fInactiveCodeHighlighting.install(fEditor);
|
||||||
|
if (refresh) {
|
||||||
|
fInactiveCodeHighlighting.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -396,133 +282,16 @@ public class CSourceViewerDecorationSupport
|
||||||
*/
|
*/
|
||||||
private void hideInactiveCodePositions() {
|
private void hideInactiveCodePositions() {
|
||||||
if (fLineBackgroundPainter != null) {
|
if (fLineBackgroundPainter != null) {
|
||||||
|
if (fInactiveCodeHighlighting != null) {
|
||||||
|
fInactiveCodeHighlighting.dispose();
|
||||||
|
fInactiveCodeHighlighting= null;
|
||||||
|
}
|
||||||
if (!isCLPActive()) {
|
if (!isCLPActive()) {
|
||||||
uninstallLineBackgroundPainter();
|
uninstallLineBackgroundPainter();
|
||||||
} else {
|
|
||||||
fLineBackgroundPainter.setHighlightPositions(Collections.EMPTY_LIST);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void inactiveCodePositionsChanged(List inactiveCodePositions) {
|
|
||||||
if (fLineBackgroundPainter != null) {
|
|
||||||
if (!inactiveCodePositions.isEmpty()) {
|
|
||||||
IPositionConverter pt = CCorePlugin.getPositionTrackerManager().findPositionConverter(fTranslationUnit.getPath(), fParseTimeStamp);
|
|
||||||
if (pt != null) {
|
|
||||||
List convertedPositions = new ArrayList(inactiveCodePositions.size());
|
|
||||||
for (Iterator iter = inactiveCodePositions.iterator(); iter
|
|
||||||
.hasNext();) {
|
|
||||||
IRegion pos = (IRegion) iter.next();
|
|
||||||
convertedPositions.add(new ReusableRegion(pt.historicToActual(pos)));
|
|
||||||
}
|
|
||||||
inactiveCodePositions = convertedPositions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fLineBackgroundPainter.setHighlightPositions(inactiveCodePositions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Collect source positions of preprocessor-hidden branches
|
|
||||||
* in the given translation unit.
|
|
||||||
*
|
|
||||||
* @param translationUnit the {@link IASTTranslationUnit}, may be <code>null</code>
|
|
||||||
* @return a {@link List} of {@link IRegion}s
|
|
||||||
*/
|
|
||||||
private static List collectInactiveCodePositions(IASTTranslationUnit translationUnit) {
|
|
||||||
if (translationUnit == null) {
|
|
||||||
return Collections.EMPTY_LIST;
|
|
||||||
}
|
|
||||||
String fileName = translationUnit.getFilePath();
|
|
||||||
if (fileName == null) {
|
|
||||||
return Collections.EMPTY_LIST;
|
|
||||||
}
|
|
||||||
List positions = new ArrayList();
|
|
||||||
int inactiveCodeStart = -1;
|
|
||||||
boolean inInactiveCode = false;
|
|
||||||
Stack inactiveCodeStack = new Stack();
|
|
||||||
// TLETODO [performance] This does not look very efficient
|
|
||||||
IASTPreprocessorStatement[] preprocStmts = translationUnit.getAllPreprocessorStatements();
|
|
||||||
for (int i = 0; i < preprocStmts.length; i++) {
|
|
||||||
IASTPreprocessorStatement statement = preprocStmts[i];
|
|
||||||
if (!fileName.equals(statement.getContainingFilename())) {
|
|
||||||
// preprocessor directive is from a different file
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (statement instanceof IASTPreprocessorIfStatement) {
|
|
||||||
IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement;
|
|
||||||
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
|
||||||
if (!ifStmt.taken()) {
|
|
||||||
if (!inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = ifStmt.getNodeLocations()[0];
|
|
||||||
inactiveCodeStart = nodeLocation.getNodeOffset();
|
|
||||||
inInactiveCode = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (statement instanceof IASTPreprocessorIfdefStatement) {
|
|
||||||
IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement;
|
|
||||||
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
|
||||||
if (!ifdefStmt.taken()) {
|
|
||||||
if (!inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = ifdefStmt.getNodeLocations()[0];
|
|
||||||
inactiveCodeStart = nodeLocation.getNodeOffset();
|
|
||||||
inInactiveCode = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (statement instanceof IASTPreprocessorIfndefStatement) {
|
|
||||||
IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement;
|
|
||||||
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
|
||||||
if (!ifndefStmt.taken()) {
|
|
||||||
if (!inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = ifndefStmt.getNodeLocations()[0];
|
|
||||||
inactiveCodeStart = nodeLocation.getNodeOffset();
|
|
||||||
inInactiveCode = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (statement instanceof IASTPreprocessorElseStatement) {
|
|
||||||
IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement;
|
|
||||||
if (!elseStmt.taken() && !inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0];
|
|
||||||
inactiveCodeStart = nodeLocation.getNodeOffset();
|
|
||||||
inInactiveCode = true;
|
|
||||||
} else if (elseStmt.taken() && inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0];
|
|
||||||
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
|
||||||
positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));
|
|
||||||
inInactiveCode = false;
|
|
||||||
}
|
|
||||||
} else if (statement instanceof IASTPreprocessorElifStatement) {
|
|
||||||
IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement)statement;
|
|
||||||
if (!elifStmt.taken() && !inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0];
|
|
||||||
inactiveCodeStart = nodeLocation.getNodeOffset();
|
|
||||||
inInactiveCode = true;
|
|
||||||
} else if (elifStmt.taken() && inInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0];
|
|
||||||
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
|
||||||
positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));
|
|
||||||
inInactiveCode = false;
|
|
||||||
}
|
|
||||||
} else if (statement instanceof IASTPreprocessorEndifStatement) {
|
|
||||||
IASTPreprocessorEndifStatement endifStmt = (IASTPreprocessorEndifStatement)statement;
|
|
||||||
try {
|
|
||||||
boolean wasInInactiveCode = ((Boolean)inactiveCodeStack.pop()).booleanValue();
|
|
||||||
if (inInactiveCode && !wasInInactiveCode) {
|
|
||||||
IASTNodeLocation nodeLocation = endifStmt.getNodeLocations()[0];
|
|
||||||
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
|
||||||
positions.add(new ReusableRegion(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart));
|
|
||||||
}
|
|
||||||
inInactiveCode = wasInInactiveCode;
|
|
||||||
}
|
|
||||||
catch( EmptyStackException e) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (inInactiveCode) {
|
|
||||||
// handle dangling #if?
|
|
||||||
}
|
|
||||||
return positions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#setCursorLinePainterPreferenceKeys(java.lang.String, java.lang.String)
|
* @see org.eclipse.ui.texteditor.SourceViewerDecorationSupport#setCursorLinePainterPreferenceKeys(java.lang.String, java.lang.String)
|
||||||
*/
|
*/
|
||||||
|
@ -543,4 +312,5 @@ public class CSourceViewerDecorationSupport
|
||||||
fInactiveCodeEnableKey = enableKey;
|
fInactiveCodeEnableKey = enableKey;
|
||||||
fInactiveCodeColorKey = colorKey;
|
fInactiveCodeColorKey = colorKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,294 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2006 Wind River Systems, Inc. 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:
|
||||||
|
* Anton Leherbauer (Wind River Systems) - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EmptyStackException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.TypedPosition;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.IPositionConverter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElifStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorElseStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorEndifStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfdefStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorIfndefStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.LineBackgroundPainter;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.ICReconcilingListener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TLETODO Document InactiveCodeHighlighting.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class InactiveCodeHighlighting implements ICReconcilingListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of <code>IRegion</code> that can be reused
|
||||||
|
* by setting the offset and the length.
|
||||||
|
*/
|
||||||
|
private static class HighlightPosition extends TypedPosition implements IRegion {
|
||||||
|
public HighlightPosition(int offset, int length, String type) {
|
||||||
|
super(offset, length, type);
|
||||||
|
}
|
||||||
|
public HighlightPosition(IRegion region, String type) {
|
||||||
|
super(region.getOffset(), region.getLength(), type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** The line background painter */
|
||||||
|
private LineBackgroundPainter fLineBackgroundPainter;
|
||||||
|
/** The key for inactive code positions in the background painter */
|
||||||
|
private String fHighlightKey;
|
||||||
|
/** The current translation unit */
|
||||||
|
private ITranslationUnit fTranslationUnit;
|
||||||
|
/** The background job doing the AST parsing */
|
||||||
|
private Job fUpdateJob;
|
||||||
|
/** The lock for job manipulation */
|
||||||
|
private Object fJobLock = new Object();
|
||||||
|
/** The editor this is installed on */
|
||||||
|
private CEditor fEditor;
|
||||||
|
/** The list of currently highlighted positions */
|
||||||
|
private List fInactiveCodePositions= Collections.EMPTY_LIST;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param lineBackgroundPainter
|
||||||
|
*/
|
||||||
|
public InactiveCodeHighlighting(LineBackgroundPainter lineBackgroundPainter, String highlightKey) {
|
||||||
|
fLineBackgroundPainter= lineBackgroundPainter;
|
||||||
|
fHighlightKey= highlightKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule update of the inactive code positions in the background.
|
||||||
|
*/
|
||||||
|
private void scheduleJob() {
|
||||||
|
synchronized (fJobLock) {
|
||||||
|
if (fUpdateJob == null) {
|
||||||
|
fUpdateJob = new Job(CEditorMessages.getString("InactiveCodeHighlighting_job")) { //$NON-NLS-1$
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
IStatus result = Status.OK_STATUS;
|
||||||
|
if (fTranslationUnit != null) {
|
||||||
|
IASTTranslationUnit ast= CUIPlugin.getDefault().getASTProvider().getAST(fTranslationUnit, ASTProvider.WAIT_YES, monitor);
|
||||||
|
reconciled(ast, null, monitor);
|
||||||
|
}
|
||||||
|
if (monitor.isCanceled()) {
|
||||||
|
result = Status.CANCEL_STATUS;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fUpdateJob.setPriority(Job.DECORATE);
|
||||||
|
}
|
||||||
|
if (fUpdateJob.getState() == Job.NONE) {
|
||||||
|
// schedule later if AST is not available yet
|
||||||
|
fUpdateJob.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param editor
|
||||||
|
*/
|
||||||
|
public void install(CEditor editor) {
|
||||||
|
assert fEditor == null;
|
||||||
|
fEditor= editor;
|
||||||
|
fEditor.addReconcileListener(this);
|
||||||
|
ICElement cElement= fEditor.getInputCElement();
|
||||||
|
if (cElement instanceof ITranslationUnit) {
|
||||||
|
fTranslationUnit = (ITranslationUnit)cElement;
|
||||||
|
} else {
|
||||||
|
fTranslationUnit = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void uninstall() {
|
||||||
|
if (fLineBackgroundPainter != null) {
|
||||||
|
fLineBackgroundPainter.removeHighlightPositions(fInactiveCodePositions);
|
||||||
|
fInactiveCodePositions= Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
if (fEditor != null) {
|
||||||
|
fEditor.removeReconcileListener(this);
|
||||||
|
fEditor= null;
|
||||||
|
fTranslationUnit= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
uninstall();
|
||||||
|
fLineBackgroundPainter= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force refresh.
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
scheduleJob();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#aboutToBeReconciled()
|
||||||
|
*/
|
||||||
|
public void aboutToBeReconciled() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, IPositionConverter, IProgressMonitor)
|
||||||
|
*/
|
||||||
|
public void reconciled(IASTTranslationUnit ast, final IPositionConverter positionTracker, IProgressMonitor progressMonitor) {
|
||||||
|
if (progressMonitor != null && progressMonitor.isCanceled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List newInactiveCodePositions = collectInactiveCodePositions(ast);
|
||||||
|
if (positionTracker != null) {
|
||||||
|
for (int i = 0, sz = newInactiveCodePositions.size(); i < sz; i++) {
|
||||||
|
IRegion pos = (IRegion) newInactiveCodePositions.get(i);
|
||||||
|
newInactiveCodePositions.set(i, new HighlightPosition(positionTracker.historicToActual(pos), fHighlightKey));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Runnable updater = new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (fEditor != null && fLineBackgroundPainter != null) {
|
||||||
|
fLineBackgroundPainter.replaceHighlightPositions(fInactiveCodePositions, newInactiveCodePositions);
|
||||||
|
fInactiveCodePositions= newInactiveCodePositions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (fEditor != null) {
|
||||||
|
Display.getDefault().asyncExec(updater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collect source positions of preprocessor-hidden branches
|
||||||
|
* in the given translation unit.
|
||||||
|
*
|
||||||
|
* @param translationUnit the {@link IASTTranslationUnit}, may be <code>null</code>
|
||||||
|
* @return a {@link List} of {@link IRegion}s
|
||||||
|
*/
|
||||||
|
private List collectInactiveCodePositions(IASTTranslationUnit translationUnit) {
|
||||||
|
if (translationUnit == null) {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
String fileName = translationUnit.getFilePath();
|
||||||
|
if (fileName == null) {
|
||||||
|
return Collections.EMPTY_LIST;
|
||||||
|
}
|
||||||
|
List positions = new ArrayList();
|
||||||
|
int inactiveCodeStart = -1;
|
||||||
|
boolean inInactiveCode = false;
|
||||||
|
Stack inactiveCodeStack = new Stack();
|
||||||
|
|
||||||
|
IASTPreprocessorStatement[] preprocStmts = translationUnit.getAllPreprocessorStatements();
|
||||||
|
|
||||||
|
for (int i = 0; i < preprocStmts.length; i++) {
|
||||||
|
IASTPreprocessorStatement statement = preprocStmts[i];
|
||||||
|
if (!fileName.equals(statement.getContainingFilename())) {
|
||||||
|
// preprocessor directive is from a different file
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (statement instanceof IASTPreprocessorIfStatement) {
|
||||||
|
IASTPreprocessorIfStatement ifStmt = (IASTPreprocessorIfStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = ifStmt.getNodeLocations()[0];
|
||||||
|
inactiveCodeStart = nodeLocation.getNodeOffset();
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorIfdefStatement) {
|
||||||
|
IASTPreprocessorIfdefStatement ifdefStmt = (IASTPreprocessorIfdefStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifdefStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = ifdefStmt.getNodeLocations()[0];
|
||||||
|
inactiveCodeStart = nodeLocation.getNodeOffset();
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorIfndefStatement) {
|
||||||
|
IASTPreprocessorIfndefStatement ifndefStmt = (IASTPreprocessorIfndefStatement)statement;
|
||||||
|
inactiveCodeStack.push(Boolean.valueOf(inInactiveCode));
|
||||||
|
if (!ifndefStmt.taken()) {
|
||||||
|
if (!inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = ifndefStmt.getNodeLocations()[0];
|
||||||
|
inactiveCodeStart = nodeLocation.getNodeOffset();
|
||||||
|
inInactiveCode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorElseStatement) {
|
||||||
|
IASTPreprocessorElseStatement elseStmt = (IASTPreprocessorElseStatement)statement;
|
||||||
|
if (!elseStmt.taken() && !inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0];
|
||||||
|
inactiveCodeStart = nodeLocation.getNodeOffset();
|
||||||
|
inInactiveCode = true;
|
||||||
|
} else if (elseStmt.taken() && inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = elseStmt.getNodeLocations()[0];
|
||||||
|
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
||||||
|
positions.add(new HighlightPosition(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart, fHighlightKey));
|
||||||
|
inInactiveCode = false;
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorElifStatement) {
|
||||||
|
IASTPreprocessorElifStatement elifStmt = (IASTPreprocessorElifStatement)statement;
|
||||||
|
if (!elifStmt.taken() && !inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0];
|
||||||
|
inactiveCodeStart = nodeLocation.getNodeOffset();
|
||||||
|
inInactiveCode = true;
|
||||||
|
} else if (elifStmt.taken() && inInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = elifStmt.getNodeLocations()[0];
|
||||||
|
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
||||||
|
positions.add(new HighlightPosition(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart, fHighlightKey));
|
||||||
|
inInactiveCode = false;
|
||||||
|
}
|
||||||
|
} else if (statement instanceof IASTPreprocessorEndifStatement) {
|
||||||
|
IASTPreprocessorEndifStatement endifStmt = (IASTPreprocessorEndifStatement)statement;
|
||||||
|
try {
|
||||||
|
boolean wasInInactiveCode = ((Boolean)inactiveCodeStack.pop()).booleanValue();
|
||||||
|
if (inInactiveCode && !wasInInactiveCode) {
|
||||||
|
IASTNodeLocation nodeLocation = endifStmt.getNodeLocations()[0];
|
||||||
|
int inactiveCodeEnd = nodeLocation.getNodeOffset() + nodeLocation.getNodeLength();
|
||||||
|
positions.add(new HighlightPosition(inactiveCodeStart, inactiveCodeEnd - inactiveCodeStart, fHighlightKey));
|
||||||
|
}
|
||||||
|
inInactiveCode = wasInInactiveCode;
|
||||||
|
}
|
||||||
|
catch( EmptyStackException e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (inInactiveCode) {
|
||||||
|
// handle dangling #if?
|
||||||
|
}
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public abstract class SemanticHighlighting {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the preference key, will be augmented by a prefix and a suffix for each preference
|
||||||
|
*/
|
||||||
|
public abstract String getPreferenceKey();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the default text color
|
||||||
|
*/
|
||||||
|
public RGB getDefaultTextColor() {
|
||||||
|
return new RGB(0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the text attribute bold is set by default
|
||||||
|
*/
|
||||||
|
public boolean isBoldByDefault() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the text attribute italic is set by default
|
||||||
|
*/
|
||||||
|
public boolean isItalicByDefault() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the text attribute strikethrough is set by default
|
||||||
|
*/
|
||||||
|
public boolean isStrikethroughByDefault() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the text attribute underline is set by default
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
|
public boolean isUnderlineByDefault() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> if the text attribute italic is enabled by default
|
||||||
|
*/
|
||||||
|
public abstract boolean isEnabledByDefault();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the display name
|
||||||
|
*/
|
||||||
|
public abstract String getDisplayName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> iff the semantic highlighting consumes the semantic token.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Implementors are not allowed to keep a reference on the token or on any object
|
||||||
|
* retrieved from the token.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param token the semantic token for a {@link org.eclipse.cdt.core.dom.ast.IASTName}
|
||||||
|
* @return <code>true</code> iff the semantic highlighting consumes the semantic token
|
||||||
|
*/
|
||||||
|
public abstract boolean consumes(SemanticToken token);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> iff the semantic highlighting consumes the
|
||||||
|
* semantic token.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Implementors are not allowed to keep a reference on the token or on
|
||||||
|
* any object retrieved from the token.
|
||||||
|
* </p>
|
||||||
|
* @param token the semantic token for a
|
||||||
|
* {@link org.eclipse.cdt.core.dom.ast.IASTLiteralExpression}
|
||||||
|
* @return <code>true</code> iff the semantic highlighting consumes the
|
||||||
|
* semantic token
|
||||||
|
*/
|
||||||
|
public boolean consumesLiteral(SemanticToken token) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,632 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.preference.PreferenceConverter;
|
||||||
|
import org.eclipse.jface.resource.StringConverter;
|
||||||
|
import org.eclipse.jface.text.Position;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.text.TextAttribute;
|
||||||
|
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||||
|
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.custom.StyleRange;
|
||||||
|
import org.eclipse.swt.graphics.Color;
|
||||||
|
import org.eclipse.swt.graphics.RGB;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CPresentationReconciler;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CSourceViewerConfiguration;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.IColorManager;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.IColorManagerExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting manager.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SemanticHighlightingManager implements IPropertyChangeListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlighting style.
|
||||||
|
*/
|
||||||
|
static class HighlightingStyle {
|
||||||
|
|
||||||
|
/** Text attribute */
|
||||||
|
private TextAttribute fTextAttribute;
|
||||||
|
/** Enabled state */
|
||||||
|
private boolean fIsEnabled;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize with the given text attribute.
|
||||||
|
* @param textAttribute The text attribute
|
||||||
|
* @param isEnabled the enabled state
|
||||||
|
*/
|
||||||
|
public HighlightingStyle(TextAttribute textAttribute, boolean isEnabled) {
|
||||||
|
setTextAttribute(textAttribute);
|
||||||
|
setEnabled(isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the text attribute.
|
||||||
|
*/
|
||||||
|
public TextAttribute getTextAttribute() {
|
||||||
|
return fTextAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param textAttribute The background to set.
|
||||||
|
*/
|
||||||
|
public void setTextAttribute(TextAttribute textAttribute) {
|
||||||
|
fTextAttribute= textAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the enabled state
|
||||||
|
*/
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return fIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param isEnabled the new enabled state
|
||||||
|
*/
|
||||||
|
public void setEnabled(boolean isEnabled) {
|
||||||
|
fIsEnabled= isEnabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlighted Positions.
|
||||||
|
*/
|
||||||
|
static class HighlightedPosition extends Position {
|
||||||
|
|
||||||
|
/** Highlighting of the position */
|
||||||
|
private HighlightingStyle fStyle;
|
||||||
|
|
||||||
|
/** Lock object */
|
||||||
|
private Object fLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the styled positions with the given offset, length and foreground color.
|
||||||
|
*
|
||||||
|
* @param offset The position offset
|
||||||
|
* @param length The position length
|
||||||
|
* @param highlighting The position's highlighting
|
||||||
|
* @param lock The lock object
|
||||||
|
*/
|
||||||
|
public HighlightedPosition(int offset, int length, HighlightingStyle highlighting, Object lock) {
|
||||||
|
super(offset, length);
|
||||||
|
fStyle= highlighting;
|
||||||
|
fLock= lock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns a corresponding style range.
|
||||||
|
*/
|
||||||
|
public StyleRange createStyleRange() {
|
||||||
|
int len= 0;
|
||||||
|
if (fStyle.isEnabled())
|
||||||
|
len= getLength();
|
||||||
|
|
||||||
|
TextAttribute textAttribute= fStyle.getTextAttribute();
|
||||||
|
int style= textAttribute.getStyle();
|
||||||
|
int fontStyle= style & (SWT.ITALIC | SWT.BOLD | SWT.NORMAL);
|
||||||
|
StyleRange styleRange= new StyleRange(getOffset(), len, textAttribute.getForeground(), textAttribute.getBackground(), fontStyle);
|
||||||
|
styleRange.strikeout= (style & TextAttribute.STRIKETHROUGH) != 0;
|
||||||
|
styleRange.underline= (style & TextAttribute.UNDERLINE) != 0;
|
||||||
|
|
||||||
|
return styleRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses reference equality for the highlighting.
|
||||||
|
*
|
||||||
|
* @param off The offset
|
||||||
|
* @param len The length
|
||||||
|
* @param highlighting The highlighting
|
||||||
|
* @return <code>true</code> iff the given offset, length and highlighting are equal to the internal ones.
|
||||||
|
*/
|
||||||
|
public boolean isEqual(int off, int len, HighlightingStyle highlighting) {
|
||||||
|
synchronized (fLock) {
|
||||||
|
return !isDeleted() && getOffset() == off && getLength() == len && fStyle == highlighting;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is this position contained in the given range (inclusive)? Synchronizes on position updater.
|
||||||
|
*
|
||||||
|
* @param off The range offset
|
||||||
|
* @param len The range length
|
||||||
|
* @return <code>true</code> iff this position is not delete and contained in the given range.
|
||||||
|
*/
|
||||||
|
public boolean isContained(int off, int len) {
|
||||||
|
synchronized (fLock) {
|
||||||
|
return !isDeleted() && off <= getOffset() && off + len >= getOffset() + getLength();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(int off, int len) {
|
||||||
|
synchronized (fLock) {
|
||||||
|
super.setOffset(off);
|
||||||
|
super.setLength(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Position#setLength(int)
|
||||||
|
*/
|
||||||
|
public void setLength(int length) {
|
||||||
|
synchronized (fLock) {
|
||||||
|
super.setLength(length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Position#setOffset(int)
|
||||||
|
*/
|
||||||
|
public void setOffset(int offset) {
|
||||||
|
synchronized (fLock) {
|
||||||
|
super.setOffset(offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Position#delete()
|
||||||
|
*/
|
||||||
|
public void delete() {
|
||||||
|
synchronized (fLock) {
|
||||||
|
super.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Position#undelete()
|
||||||
|
*/
|
||||||
|
public void undelete() {
|
||||||
|
synchronized (fLock) {
|
||||||
|
super.undelete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the highlighting.
|
||||||
|
*/
|
||||||
|
public HighlightingStyle getHighlighting() {
|
||||||
|
return fStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Highlighted ranges.
|
||||||
|
*/
|
||||||
|
public static class HighlightedRange extends Region {
|
||||||
|
/** The highlighting key as returned by {@link SemanticHighlighting#getPreferenceKey()}. */
|
||||||
|
private String fKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize with the given offset, length and highlighting key.
|
||||||
|
*
|
||||||
|
* @param offset
|
||||||
|
* @param length
|
||||||
|
* @param key the highlighting key as returned by {@link SemanticHighlighting#getPreferenceKey()}
|
||||||
|
*/
|
||||||
|
public HighlightedRange(int offset, int length, String key) {
|
||||||
|
super(offset, length);
|
||||||
|
fKey= key;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the highlighting key as returned by {@link SemanticHighlighting#getPreferenceKey()}
|
||||||
|
*/
|
||||||
|
public String getKey() {
|
||||||
|
return fKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Region#equals(java.lang.Object)
|
||||||
|
*/
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return super.equals(o) && o instanceof HighlightedRange && fKey.equals(((HighlightedRange)o).getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.Region#hashCode()
|
||||||
|
*/
|
||||||
|
public int hashCode() {
|
||||||
|
return super.hashCode() | fKey.hashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Semantic highlighting presenter */
|
||||||
|
private SemanticHighlightingPresenter fPresenter;
|
||||||
|
/** Semantic highlighting reconciler */
|
||||||
|
private SemanticHighlightingReconciler fReconciler;
|
||||||
|
|
||||||
|
/** Semantic highlightings */
|
||||||
|
private SemanticHighlighting[] fSemanticHighlightings;
|
||||||
|
/** Highlightings */
|
||||||
|
private HighlightingStyle[] fHighlightings;
|
||||||
|
|
||||||
|
/** The editor */
|
||||||
|
private CEditor fEditor;
|
||||||
|
/** The source viewer */
|
||||||
|
private CSourceViewer fSourceViewer;
|
||||||
|
/** The color manager */
|
||||||
|
private IColorManager fColorManager;
|
||||||
|
/** The preference store */
|
||||||
|
private IPreferenceStore fPreferenceStore;
|
||||||
|
/** The source viewer configuration */
|
||||||
|
private CSourceViewerConfiguration fConfiguration;
|
||||||
|
/** The presentation reconciler */
|
||||||
|
private CPresentationReconciler fPresentationReconciler;
|
||||||
|
|
||||||
|
/** The hard-coded ranges */
|
||||||
|
private HighlightedRange[][] fHardcodedRanges;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install the semantic highlighting on the given editor infrastructure
|
||||||
|
*
|
||||||
|
* @param editor The C editor
|
||||||
|
* @param sourceViewer The source viewer
|
||||||
|
* @param colorManager The color manager
|
||||||
|
* @param preferenceStore The preference store
|
||||||
|
*/
|
||||||
|
public void install(CEditor editor, CSourceViewer sourceViewer, IColorManager colorManager, IPreferenceStore preferenceStore) {
|
||||||
|
fEditor= editor;
|
||||||
|
fSourceViewer= sourceViewer;
|
||||||
|
fColorManager= colorManager;
|
||||||
|
fPreferenceStore= preferenceStore;
|
||||||
|
if (fEditor != null) {
|
||||||
|
fConfiguration= new CSourceViewerConfiguration(CUIPlugin.getDefault().getTextTools(), fEditor);
|
||||||
|
// fConfiguration= new CSourceViewerConfiguration(colorManager, preferenceStore, editor, ICPartitions.C_PARTITIONING);
|
||||||
|
fPresentationReconciler= (CPresentationReconciler) fConfiguration.getPresentationReconciler(sourceViewer);
|
||||||
|
} else {
|
||||||
|
fConfiguration= null;
|
||||||
|
fPresentationReconciler= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fPreferenceStore.addPropertyChangeListener(this);
|
||||||
|
|
||||||
|
if (isEnabled())
|
||||||
|
enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install the semantic highlighting on the given source viewer infrastructure. No reconciliation will be performed.
|
||||||
|
*
|
||||||
|
* @param sourceViewer the source viewer
|
||||||
|
* @param colorManager the color manager
|
||||||
|
* @param preferenceStore the preference store
|
||||||
|
* @param hardcodedRanges the hard-coded ranges to be highlighted
|
||||||
|
*/
|
||||||
|
public void install(CSourceViewer sourceViewer, IColorManager colorManager, IPreferenceStore preferenceStore, HighlightedRange[][] hardcodedRanges) {
|
||||||
|
fHardcodedRanges= hardcodedRanges;
|
||||||
|
install(null, sourceViewer, colorManager, preferenceStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable semantic highlighting.
|
||||||
|
*/
|
||||||
|
private void enable() {
|
||||||
|
initializeHighlightings();
|
||||||
|
|
||||||
|
fPresenter= new SemanticHighlightingPresenter();
|
||||||
|
fPresenter.install(fSourceViewer, fPresentationReconciler);
|
||||||
|
|
||||||
|
if (fEditor != null) {
|
||||||
|
fReconciler= new SemanticHighlightingReconciler();
|
||||||
|
fReconciler.install(fEditor, fSourceViewer, fPresenter, fSemanticHighlightings, fHighlightings);
|
||||||
|
} else {
|
||||||
|
fPresenter.updatePresentation(null, createHardcodedPositions(), new HighlightedPosition[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the hard-coded positions from the hard-coded ranges
|
||||||
|
*
|
||||||
|
* @return the hard-coded positions
|
||||||
|
*/
|
||||||
|
private HighlightedPosition[] createHardcodedPositions() {
|
||||||
|
List positions= new ArrayList();
|
||||||
|
for (int i= 0; i < fHardcodedRanges.length; i++) {
|
||||||
|
HighlightedRange range= null;
|
||||||
|
HighlightingStyle hl= null;
|
||||||
|
for (int j= 0; j < fHardcodedRanges[i].length; j++ ) {
|
||||||
|
hl= getHighlighting(fHardcodedRanges[i][j].getKey());
|
||||||
|
if (hl.isEnabled()) {
|
||||||
|
range= fHardcodedRanges[i][j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (range != null)
|
||||||
|
positions.add(fPresenter.createHighlightedPosition(range.getOffset(), range.getLength(), hl));
|
||||||
|
}
|
||||||
|
return (HighlightedPosition[]) positions.toArray(new HighlightedPosition[positions.size()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the highlighting corresponding to the given key.
|
||||||
|
*
|
||||||
|
* @param key the highlighting key as returned by {@link SemanticHighlighting#getPreferenceKey()}
|
||||||
|
* @return the corresponding highlighting
|
||||||
|
*/
|
||||||
|
private HighlightingStyle getHighlighting(String key) {
|
||||||
|
for (int i= 0; i < fSemanticHighlightings.length; i++) {
|
||||||
|
SemanticHighlighting semanticHighlighting= fSemanticHighlightings[i];
|
||||||
|
if (key.equals(semanticHighlighting.getPreferenceKey()))
|
||||||
|
return fHighlightings[i];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall the semantic highlighting
|
||||||
|
*/
|
||||||
|
public void uninstall() {
|
||||||
|
disable();
|
||||||
|
|
||||||
|
if (fPreferenceStore != null) {
|
||||||
|
fPreferenceStore.removePropertyChangeListener(this);
|
||||||
|
fPreferenceStore= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fEditor= null;
|
||||||
|
fSourceViewer= null;
|
||||||
|
fColorManager= null;
|
||||||
|
fConfiguration= null;
|
||||||
|
fPresentationReconciler= null;
|
||||||
|
fHardcodedRanges= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable semantic highlighting.
|
||||||
|
*/
|
||||||
|
private void disable() {
|
||||||
|
if (fReconciler != null) {
|
||||||
|
fReconciler.uninstall();
|
||||||
|
fReconciler= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fPresenter != null) {
|
||||||
|
fPresenter.uninstall();
|
||||||
|
fPresenter= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fSemanticHighlightings != null)
|
||||||
|
disposeHighlightings();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return <code>true</code> iff semantic highlighting is enabled in the preferences
|
||||||
|
*/
|
||||||
|
private boolean isEnabled() {
|
||||||
|
return SemanticHighlightings.isEnabled(fPreferenceStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize semantic highlightings.
|
||||||
|
*/
|
||||||
|
private void initializeHighlightings() {
|
||||||
|
fSemanticHighlightings= SemanticHighlightings.getSemanticHighlightings();
|
||||||
|
fHighlightings= new HighlightingStyle[fSemanticHighlightings.length];
|
||||||
|
|
||||||
|
for (int i= 0, n= fSemanticHighlightings.length; i < n; i++) {
|
||||||
|
SemanticHighlighting semanticHighlighting= fSemanticHighlightings[i];
|
||||||
|
String colorKey= SemanticHighlightings.getColorPreferenceKey(semanticHighlighting);
|
||||||
|
addColor(colorKey);
|
||||||
|
|
||||||
|
String boldKey= SemanticHighlightings.getBoldPreferenceKey(semanticHighlighting);
|
||||||
|
int style= fPreferenceStore.getBoolean(boldKey) ? SWT.BOLD : SWT.NORMAL;
|
||||||
|
|
||||||
|
String italicKey= SemanticHighlightings.getItalicPreferenceKey(semanticHighlighting);
|
||||||
|
if (fPreferenceStore.getBoolean(italicKey))
|
||||||
|
style |= SWT.ITALIC;
|
||||||
|
|
||||||
|
String strikethroughKey= SemanticHighlightings.getStrikethroughPreferenceKey(semanticHighlighting);
|
||||||
|
if (fPreferenceStore.getBoolean(strikethroughKey))
|
||||||
|
style |= TextAttribute.STRIKETHROUGH;
|
||||||
|
|
||||||
|
String underlineKey= SemanticHighlightings.getUnderlinePreferenceKey(semanticHighlighting);
|
||||||
|
if (fPreferenceStore.getBoolean(underlineKey))
|
||||||
|
style |= TextAttribute.UNDERLINE;
|
||||||
|
|
||||||
|
boolean isEnabled= fPreferenceStore.getBoolean(SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting));
|
||||||
|
|
||||||
|
fHighlightings[i]= new HighlightingStyle(new TextAttribute(fColorManager.getColor(PreferenceConverter.getColor(fPreferenceStore, colorKey)), null, style), isEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dispose the semantic highlightings.
|
||||||
|
*/
|
||||||
|
private void disposeHighlightings() {
|
||||||
|
for (int i= 0, n= fSemanticHighlightings.length; i < n; i++)
|
||||||
|
removeColor(SemanticHighlightings.getColorPreferenceKey(fSemanticHighlightings[i]));
|
||||||
|
|
||||||
|
fSemanticHighlightings= null;
|
||||||
|
fHighlightings= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
|
||||||
|
*/
|
||||||
|
public void propertyChange(PropertyChangeEvent event) {
|
||||||
|
handlePropertyChangeEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the given property change event
|
||||||
|
*
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void handlePropertyChangeEvent(PropertyChangeEvent event) {
|
||||||
|
if (fPreferenceStore == null)
|
||||||
|
return; // Uninstalled during event notification
|
||||||
|
|
||||||
|
if (fConfiguration != null)
|
||||||
|
fConfiguration.handlePropertyChangeEvent(event);
|
||||||
|
|
||||||
|
if (SemanticHighlightings.affectsEnablement(fPreferenceStore, event)) {
|
||||||
|
if (isEnabled())
|
||||||
|
enable();
|
||||||
|
else
|
||||||
|
disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isEnabled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
boolean refreshNeeded= false;
|
||||||
|
|
||||||
|
for (int i= 0, n= fSemanticHighlightings.length; i < n; i++) {
|
||||||
|
SemanticHighlighting semanticHighlighting= fSemanticHighlightings[i];
|
||||||
|
|
||||||
|
String colorKey= SemanticHighlightings.getColorPreferenceKey(semanticHighlighting);
|
||||||
|
if (colorKey.equals(event.getProperty())) {
|
||||||
|
adaptToTextForegroundChange(fHighlightings[i], event);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String boldKey= SemanticHighlightings.getBoldPreferenceKey(semanticHighlighting);
|
||||||
|
if (boldKey.equals(event.getProperty())) {
|
||||||
|
adaptToTextStyleChange(fHighlightings[i], event, SWT.BOLD);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String italicKey= SemanticHighlightings.getItalicPreferenceKey(semanticHighlighting);
|
||||||
|
if (italicKey.equals(event.getProperty())) {
|
||||||
|
adaptToTextStyleChange(fHighlightings[i], event, SWT.ITALIC);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String strikethroughKey= SemanticHighlightings.getStrikethroughPreferenceKey(semanticHighlighting);
|
||||||
|
if (strikethroughKey.equals(event.getProperty())) {
|
||||||
|
adaptToTextStyleChange(fHighlightings[i], event, TextAttribute.STRIKETHROUGH);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String underlineKey= SemanticHighlightings.getUnderlinePreferenceKey(semanticHighlighting);
|
||||||
|
if (underlineKey.equals(event.getProperty())) {
|
||||||
|
adaptToTextStyleChange(fHighlightings[i], event, TextAttribute.UNDERLINE);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String enabledKey= SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting);
|
||||||
|
if (enabledKey.equals(event.getProperty())) {
|
||||||
|
adaptToEnablementChange(fHighlightings[i], event);
|
||||||
|
fPresenter.highlightingStyleChanged(fHighlightings[i]);
|
||||||
|
refreshNeeded= true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refreshNeeded && fReconciler != null)
|
||||||
|
fReconciler.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adaptToEnablementChange(HighlightingStyle highlighting, PropertyChangeEvent event) {
|
||||||
|
Object value= event.getNewValue();
|
||||||
|
boolean eventValue;
|
||||||
|
if (value instanceof Boolean)
|
||||||
|
eventValue= ((Boolean) value).booleanValue();
|
||||||
|
else if (IPreferenceStore.TRUE.equals(value))
|
||||||
|
eventValue= true;
|
||||||
|
else
|
||||||
|
eventValue= false;
|
||||||
|
highlighting.setEnabled(eventValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adaptToTextForegroundChange(HighlightingStyle highlighting, PropertyChangeEvent event) {
|
||||||
|
RGB rgb= null;
|
||||||
|
|
||||||
|
Object value= event.getNewValue();
|
||||||
|
if (value instanceof RGB)
|
||||||
|
rgb= (RGB) value;
|
||||||
|
else if (value instanceof String)
|
||||||
|
rgb= StringConverter.asRGB((String) value);
|
||||||
|
|
||||||
|
if (rgb != null) {
|
||||||
|
|
||||||
|
String property= event.getProperty();
|
||||||
|
Color color= fColorManager.getColor(property);
|
||||||
|
|
||||||
|
if ((color == null || !rgb.equals(color.getRGB())) && fColorManager instanceof IColorManagerExtension) {
|
||||||
|
IColorManagerExtension ext= (IColorManagerExtension) fColorManager;
|
||||||
|
ext.unbindColor(property);
|
||||||
|
ext.bindColor(property, rgb);
|
||||||
|
color= fColorManager.getColor(property);
|
||||||
|
}
|
||||||
|
|
||||||
|
TextAttribute oldAttr= highlighting.getTextAttribute();
|
||||||
|
highlighting.setTextAttribute(new TextAttribute(color, oldAttr.getBackground(), oldAttr.getStyle()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adaptToTextStyleChange(HighlightingStyle highlighting, PropertyChangeEvent event, int styleAttribute) {
|
||||||
|
boolean eventValue= false;
|
||||||
|
Object value= event.getNewValue();
|
||||||
|
if (value instanceof Boolean)
|
||||||
|
eventValue= ((Boolean) value).booleanValue();
|
||||||
|
else if (IPreferenceStore.TRUE.equals(value))
|
||||||
|
eventValue= true;
|
||||||
|
|
||||||
|
TextAttribute oldAttr= highlighting.getTextAttribute();
|
||||||
|
boolean activeValue= (oldAttr.getStyle() & styleAttribute) == styleAttribute;
|
||||||
|
|
||||||
|
if (activeValue != eventValue)
|
||||||
|
highlighting.setTextAttribute(new TextAttribute(oldAttr.getForeground(), oldAttr.getBackground(), eventValue ? oldAttr.getStyle() | styleAttribute : oldAttr.getStyle() & ~styleAttribute));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addColor(String colorKey) {
|
||||||
|
if (fColorManager != null && colorKey != null && fColorManager.getColor(colorKey) == null) {
|
||||||
|
RGB rgb= PreferenceConverter.getColor(fPreferenceStore, colorKey);
|
||||||
|
if (fColorManager instanceof IColorManagerExtension) {
|
||||||
|
IColorManagerExtension ext= (IColorManagerExtension) fColorManager;
|
||||||
|
ext.unbindColor(colorKey);
|
||||||
|
ext.bindColor(colorKey, rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeColor(String colorKey) {
|
||||||
|
if (fColorManager instanceof IColorManagerExtension)
|
||||||
|
((IColorManagerExtension) fColorManager).unbindColor(colorKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force refresh of highlighting.
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
if (fReconciler != null) {
|
||||||
|
fReconciler.refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,777 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.BadLocationException;
|
||||||
|
import org.eclipse.jface.text.BadPositionCategoryException;
|
||||||
|
import org.eclipse.jface.text.DocumentEvent;
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IDocumentListener;
|
||||||
|
import org.eclipse.jface.text.IPositionUpdater;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.ISynchronizable;
|
||||||
|
import org.eclipse.jface.text.ITextInputListener;
|
||||||
|
import org.eclipse.jface.text.ITextPresentationListener;
|
||||||
|
import org.eclipse.jface.text.Position;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.swt.custom.StyleRange;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingManager.HighlightedPosition;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingManager.HighlightingStyle;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.CPresentationReconciler;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting presenter - UI thread implementation.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SemanticHighlightingPresenter implements ITextPresentationListener, ITextInputListener, IDocumentListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting position updater.
|
||||||
|
*/
|
||||||
|
private class HighlightingPositionUpdater implements IPositionUpdater {
|
||||||
|
|
||||||
|
/** The position category. */
|
||||||
|
private final String fCategory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new updater for the given <code>category</code>.
|
||||||
|
*
|
||||||
|
* @param category the new category.
|
||||||
|
*/
|
||||||
|
public HighlightingPositionUpdater(String category) {
|
||||||
|
fCategory= category;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IPositionUpdater#update(org.eclipse.jface.text.DocumentEvent)
|
||||||
|
*/
|
||||||
|
public void update(DocumentEvent event) {
|
||||||
|
|
||||||
|
int eventOffset= event.getOffset();
|
||||||
|
int eventOldLength= event.getLength();
|
||||||
|
int eventEnd= eventOffset + eventOldLength;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Position[] positions= event.getDocument().getPositions(fCategory);
|
||||||
|
|
||||||
|
for (int i= 0; i != positions.length; i++) {
|
||||||
|
|
||||||
|
HighlightedPosition position= (HighlightedPosition) positions[i];
|
||||||
|
|
||||||
|
// Also update deleted positions because they get deleted by the background thread and removed/invalidated only in the UI runnable
|
||||||
|
// if (position.isDeleted())
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
int offset= position.getOffset();
|
||||||
|
int length= position.getLength();
|
||||||
|
int end= offset + length;
|
||||||
|
|
||||||
|
if (offset > eventEnd)
|
||||||
|
updateWithPrecedingEvent(position, event);
|
||||||
|
else if (end < eventOffset)
|
||||||
|
updateWithSucceedingEvent(position, event);
|
||||||
|
else if (offset <= eventOffset && end >= eventEnd)
|
||||||
|
updateWithIncludedEvent(position, event);
|
||||||
|
else if (offset <= eventOffset)
|
||||||
|
updateWithOverEndEvent(position, event);
|
||||||
|
else if (end >= eventEnd)
|
||||||
|
updateWithOverStartEvent(position, event);
|
||||||
|
else
|
||||||
|
updateWithIncludingEvent(position, event);
|
||||||
|
}
|
||||||
|
} catch (BadPositionCategoryException e) {
|
||||||
|
// ignore and return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event precedes the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithPrecedingEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
String newText= event.getText();
|
||||||
|
int eventNewLength= newText != null ? newText.length() : 0;
|
||||||
|
int deltaLength= eventNewLength - event.getLength();
|
||||||
|
|
||||||
|
position.setOffset(position.getOffset() + deltaLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event succeeds the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithSucceedingEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event is included by the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithIncludedEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
int eventOffset= event.getOffset();
|
||||||
|
String newText= event.getText();
|
||||||
|
if (newText == null)
|
||||||
|
newText= ""; //$NON-NLS-1$
|
||||||
|
int eventNewLength= newText.length();
|
||||||
|
|
||||||
|
int deltaLength= eventNewLength - event.getLength();
|
||||||
|
|
||||||
|
int offset= position.getOffset();
|
||||||
|
int length= position.getLength();
|
||||||
|
int end= offset + length;
|
||||||
|
|
||||||
|
int includedLength= 0;
|
||||||
|
while (includedLength < eventNewLength && Character.isJavaIdentifierPart(newText.charAt(includedLength)))
|
||||||
|
includedLength++;
|
||||||
|
if (includedLength == eventNewLength)
|
||||||
|
position.setLength(length + deltaLength);
|
||||||
|
else {
|
||||||
|
int newLeftLength= eventOffset - offset + includedLength;
|
||||||
|
|
||||||
|
int excludedLength= eventNewLength;
|
||||||
|
while (excludedLength > 0 && Character.isJavaIdentifierPart(newText.charAt(excludedLength - 1)))
|
||||||
|
excludedLength--;
|
||||||
|
int newRightOffset= eventOffset + excludedLength;
|
||||||
|
int newRightLength= end + deltaLength - newRightOffset;
|
||||||
|
|
||||||
|
if (newRightLength == 0) {
|
||||||
|
position.setLength(newLeftLength);
|
||||||
|
} else {
|
||||||
|
if (newLeftLength == 0) {
|
||||||
|
position.update(newRightOffset, newRightLength);
|
||||||
|
} else {
|
||||||
|
position.setLength(newLeftLength);
|
||||||
|
addPositionFromUI(newRightOffset, newRightLength, position.getHighlighting());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event overlaps with the end of the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithOverEndEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
String newText= event.getText();
|
||||||
|
if (newText == null)
|
||||||
|
newText= ""; //$NON-NLS-1$
|
||||||
|
int eventNewLength= newText.length();
|
||||||
|
|
||||||
|
int includedLength= 0;
|
||||||
|
while (includedLength < eventNewLength && Character.isJavaIdentifierPart(newText.charAt(includedLength)))
|
||||||
|
includedLength++;
|
||||||
|
position.setLength(event.getOffset() - position.getOffset() + includedLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event overlaps with the start of the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithOverStartEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
int eventOffset= event.getOffset();
|
||||||
|
int eventEnd= eventOffset + event.getLength();
|
||||||
|
|
||||||
|
String newText= event.getText();
|
||||||
|
if (newText == null)
|
||||||
|
newText= ""; //$NON-NLS-1$
|
||||||
|
int eventNewLength= newText.length();
|
||||||
|
|
||||||
|
int excludedLength= eventNewLength;
|
||||||
|
while (excludedLength > 0 && Character.isJavaIdentifierPart(newText.charAt(excludedLength - 1)))
|
||||||
|
excludedLength--;
|
||||||
|
int deleted= eventEnd - position.getOffset();
|
||||||
|
int inserted= eventNewLength - excludedLength;
|
||||||
|
position.update(eventOffset + excludedLength, position.getLength() - deleted + inserted);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the given position with the given event. The event includes the position.
|
||||||
|
*
|
||||||
|
* @param position The position
|
||||||
|
* @param event The event
|
||||||
|
*/
|
||||||
|
private void updateWithIncludingEvent(HighlightedPosition position, DocumentEvent event) {
|
||||||
|
position.delete();
|
||||||
|
position.update(event.getOffset(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Position updater */
|
||||||
|
private IPositionUpdater fPositionUpdater= new HighlightingPositionUpdater(getPositionCategory());
|
||||||
|
|
||||||
|
/** The source viewer this semantic highlighting reconciler is installed on */
|
||||||
|
private CSourceViewer fSourceViewer;
|
||||||
|
/** The background presentation reconciler */
|
||||||
|
private CPresentationReconciler fPresentationReconciler;
|
||||||
|
|
||||||
|
/** UI's current highlighted positions - can contain <code>null</code> elements */
|
||||||
|
private List fPositions= new ArrayList();
|
||||||
|
/** UI position lock */
|
||||||
|
private Object fPositionLock= new Object();
|
||||||
|
|
||||||
|
/** <code>true</code> iff the current reconcile is canceled. */
|
||||||
|
private boolean fIsCanceled= false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates and returns a new highlighted position with the given offset, length and highlighting.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Also called from background thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param offset The offset
|
||||||
|
* @param length The length
|
||||||
|
* @param highlighting The highlighting
|
||||||
|
* @return The new highlighted position
|
||||||
|
*/
|
||||||
|
public HighlightedPosition createHighlightedPosition(int offset, int length, HighlightingStyle highlighting) {
|
||||||
|
// TODO: reuse deleted positions
|
||||||
|
return new HighlightedPosition(offset, length, highlighting, fPositionUpdater);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds all current positions to the given list.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Called from background thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param list The list
|
||||||
|
*/
|
||||||
|
public void addAllPositions(List list) {
|
||||||
|
synchronized (fPositionLock) {
|
||||||
|
list.addAll(fPositions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a text presentation in the background.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Called from background thread.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param addedPositions the added positions
|
||||||
|
* @param removedPositions the removed positions
|
||||||
|
* @return the text presentation or <code>null</code>, if reconciliation should be canceled
|
||||||
|
*/
|
||||||
|
public TextPresentation createPresentation(List addedPositions, List removedPositions) {
|
||||||
|
CSourceViewer sourceViewer= fSourceViewer;
|
||||||
|
CPresentationReconciler presentationReconciler= fPresentationReconciler;
|
||||||
|
if (sourceViewer == null || presentationReconciler == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (isCanceled())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
IDocument document= sourceViewer.getDocument();
|
||||||
|
if (document == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int minStart= Integer.MAX_VALUE;
|
||||||
|
int maxEnd= Integer.MIN_VALUE;
|
||||||
|
for (int i= 0, n= removedPositions.size(); i < n; i++) {
|
||||||
|
Position position= (Position) removedPositions.get(i);
|
||||||
|
int offset= position.getOffset();
|
||||||
|
minStart= Math.min(minStart, offset);
|
||||||
|
maxEnd= Math.max(maxEnd, offset + position.getLength());
|
||||||
|
}
|
||||||
|
for (int i= 0, n= addedPositions.size(); i < n; i++) {
|
||||||
|
Position position= (Position) addedPositions.get(i);
|
||||||
|
int offset= position.getOffset();
|
||||||
|
minStart= Math.min(minStart, offset);
|
||||||
|
maxEnd= Math.max(maxEnd, offset + position.getLength());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minStart < maxEnd)
|
||||||
|
try {
|
||||||
|
return presentationReconciler.createRepairDescription(new Region(minStart, maxEnd - minStart), document);
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
// Assume concurrent modification from UI thread
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a runnable for updating the presentation.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Called from background thread.
|
||||||
|
* </p>
|
||||||
|
* @param textPresentation the text presentation
|
||||||
|
* @param addedPositions the added positions
|
||||||
|
* @param removedPositions the removed positions
|
||||||
|
* @return the runnable or <code>null</code>, if reconciliation should be canceled
|
||||||
|
*/
|
||||||
|
public Runnable createUpdateRunnable(final TextPresentation textPresentation, List addedPositions, List removedPositions) {
|
||||||
|
if (fSourceViewer == null || textPresentation == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// TODO: do clustering of positions and post multiple fast runnables
|
||||||
|
final HighlightedPosition[] added= new SemanticHighlightingManager.HighlightedPosition[addedPositions.size()];
|
||||||
|
addedPositions.toArray(added);
|
||||||
|
final SemanticHighlightingManager.HighlightedPosition[] removed= new SemanticHighlightingManager.HighlightedPosition[removedPositions.size()];
|
||||||
|
removedPositions.toArray(removed);
|
||||||
|
|
||||||
|
if (isCanceled())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Runnable runnable= new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
updatePresentation(textPresentation, added, removed);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return runnable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate the presentation of the positions based on the given added positions and the existing deleted positions.
|
||||||
|
* Also unregisters the deleted positions from the document and patches the positions of this presenter.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Indirectly called from background thread by UI runnable.
|
||||||
|
* </p>
|
||||||
|
* @param textPresentation the text presentation or <code>null</code>, if the presentation should computed in the UI thread
|
||||||
|
* @param addedPositions the added positions
|
||||||
|
* @param removedPositions the removed positions
|
||||||
|
*/
|
||||||
|
public void updatePresentation(TextPresentation textPresentation, HighlightedPosition[] addedPositions, HighlightedPosition[] removedPositions) {
|
||||||
|
if (fSourceViewer == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// checkOrdering("added positions: ", Arrays.asList(addedPositions)); //$NON-NLS-1$
|
||||||
|
// checkOrdering("removed positions: ", Arrays.asList(removedPositions)); //$NON-NLS-1$
|
||||||
|
// checkOrdering("old positions: ", fPositions); //$NON-NLS-1$
|
||||||
|
|
||||||
|
// TODO: double-check consistency with document.getPositions(...)
|
||||||
|
// TODO: reuse removed positions
|
||||||
|
if (isCanceled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
IDocument document= fSourceViewer.getDocument();
|
||||||
|
if (document == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String positionCategory= getPositionCategory();
|
||||||
|
|
||||||
|
List removedPositionsList= Arrays.asList(removedPositions);
|
||||||
|
|
||||||
|
try {
|
||||||
|
synchronized (fPositionLock) {
|
||||||
|
List oldPositions= fPositions;
|
||||||
|
int newSize= Math.max(fPositions.size() + addedPositions.length - removedPositions.length, 10);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The following loop is a kind of merge sort: it merges two List<Position>, each
|
||||||
|
* sorted by position.offset, into one new list. The first of the two is the
|
||||||
|
* previous list of positions (oldPositions), from which any deleted positions get
|
||||||
|
* removed on the fly. The second of two is the list of added positions. The result
|
||||||
|
* is stored in newPositions.
|
||||||
|
*/
|
||||||
|
List newPositions= new ArrayList(newSize);
|
||||||
|
Position position= null;
|
||||||
|
Position addedPosition= null;
|
||||||
|
for (int i= 0, j= 0, n= oldPositions.size(), m= addedPositions.length; i < n || position != null || j < m || addedPosition != null;) {
|
||||||
|
// loop variant: i + j < old(i + j)
|
||||||
|
|
||||||
|
// a) find the next non-deleted Position from the old list
|
||||||
|
while (position == null && i < n) {
|
||||||
|
position= (Position) oldPositions.get(i++);
|
||||||
|
if (position.isDeleted() || contain(removedPositionsList, position)) {
|
||||||
|
document.removePosition(positionCategory, position);
|
||||||
|
position= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// b) find the next Position from the added list
|
||||||
|
if (addedPosition == null && j < m) {
|
||||||
|
addedPosition= addedPositions[j++];
|
||||||
|
document.addPosition(positionCategory, addedPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
// c) merge: add the next of position/addedPosition with the lower offset
|
||||||
|
if (position != null) {
|
||||||
|
if (addedPosition != null)
|
||||||
|
if (position.getOffset() <= addedPosition.getOffset()) {
|
||||||
|
newPositions.add(position);
|
||||||
|
position= null;
|
||||||
|
} else {
|
||||||
|
newPositions.add(addedPosition);
|
||||||
|
addedPosition= null;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newPositions.add(position);
|
||||||
|
position= null;
|
||||||
|
}
|
||||||
|
} else if (addedPosition != null) {
|
||||||
|
newPositions.add(addedPosition);
|
||||||
|
addedPosition= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fPositions= newPositions;
|
||||||
|
}
|
||||||
|
} catch (BadPositionCategoryException e) {
|
||||||
|
// Should not happen
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
// Should not happen
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
}
|
||||||
|
// checkOrdering("new positions: ", fPositions); //$NON-NLS-1$
|
||||||
|
|
||||||
|
if (textPresentation != null)
|
||||||
|
fSourceViewer.changeTextPresentation(textPresentation, false);
|
||||||
|
else
|
||||||
|
fSourceViewer.invalidateTextPresentation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// private void checkOrdering(String s, List positions) {
|
||||||
|
// Position previous= null;
|
||||||
|
// for (int i= 0, n= positions.size(); i < n; i++) {
|
||||||
|
// Position current= (Position) positions.get(i);
|
||||||
|
// if (previous != null && previous.getOffset() + previous.getLength() > current.getOffset())
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns <code>true</code> iff the positions contain the position.
|
||||||
|
* @param positions the positions, must be ordered by offset but may overlap
|
||||||
|
* @param position the position
|
||||||
|
* @return <code>true</code> iff the positions contain the position
|
||||||
|
*/
|
||||||
|
private boolean contain(List positions, Position position) {
|
||||||
|
return indexOf(positions, position) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns index of the position in the positions, <code>-1</code> if not found.
|
||||||
|
* @param positions the positions, must be ordered by offset but may overlap
|
||||||
|
* @param position the position
|
||||||
|
* @return the index
|
||||||
|
*/
|
||||||
|
private int indexOf(List positions, Position position) {
|
||||||
|
int index= computeIndexAtOffset(positions, position.getOffset());
|
||||||
|
int size= positions.size();
|
||||||
|
while (index < size) {
|
||||||
|
if (positions.get(index) == position)
|
||||||
|
return index;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert the given position in <code>fPositions</code>, s.t. the offsets remain in linear order.
|
||||||
|
*
|
||||||
|
* @param position The position for insertion
|
||||||
|
*/
|
||||||
|
private void insertPosition(Position position) {
|
||||||
|
int i= computeIndexAfterOffset(fPositions, position.getOffset());
|
||||||
|
fPositions.add(i, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the first position with an offset greater than the given offset.
|
||||||
|
*
|
||||||
|
* @param positions the positions, must be ordered by offset and must not overlap
|
||||||
|
* @param offset the offset
|
||||||
|
* @return the index of the last position with an offset greater than the given offset
|
||||||
|
*/
|
||||||
|
private int computeIndexAfterOffset(List positions, int offset) {
|
||||||
|
int i= -1;
|
||||||
|
int j= positions.size();
|
||||||
|
while (j - i > 1) {
|
||||||
|
int k= (i + j) >> 1;
|
||||||
|
Position position= (Position) positions.get(k);
|
||||||
|
if (position.getOffset() > offset)
|
||||||
|
j= k;
|
||||||
|
else
|
||||||
|
i= k;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the first position with an offset equal or greater than the given offset.
|
||||||
|
*
|
||||||
|
* @param positions the positions, must be ordered by offset and must not overlap
|
||||||
|
* @param offset the offset
|
||||||
|
* @return the index of the last position with an offset equal or greater than the given offset
|
||||||
|
*/
|
||||||
|
private int computeIndexAtOffset(List positions, int offset) {
|
||||||
|
int i= -1;
|
||||||
|
int j= positions.size();
|
||||||
|
while (j - i > 1) {
|
||||||
|
int k= (i + j) >> 1;
|
||||||
|
Position position= (Position) positions.get(k);
|
||||||
|
if (position.getOffset() >= offset)
|
||||||
|
j= k;
|
||||||
|
else
|
||||||
|
i= k;
|
||||||
|
}
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.ITextPresentationListener#applyTextPresentation(org.eclipse.jface.text.TextPresentation)
|
||||||
|
*/
|
||||||
|
public void applyTextPresentation(TextPresentation textPresentation) {
|
||||||
|
IRegion region= textPresentation.getExtent();
|
||||||
|
int i= computeIndexAtOffset(fPositions, region.getOffset()), n= computeIndexAtOffset(fPositions, region.getOffset() + region.getLength());
|
||||||
|
if (n - i > 2) {
|
||||||
|
List ranges= new ArrayList(n - i);
|
||||||
|
for (; i < n; i++) {
|
||||||
|
HighlightedPosition position= (HighlightedPosition) fPositions.get(i);
|
||||||
|
if (!position.isDeleted())
|
||||||
|
ranges.add(position.createStyleRange());
|
||||||
|
}
|
||||||
|
StyleRange[] array= new StyleRange[ranges.size()];
|
||||||
|
array= (StyleRange[]) ranges.toArray(array);
|
||||||
|
textPresentation.replaceStyleRanges(array);
|
||||||
|
} else {
|
||||||
|
for (; i < n; i++) {
|
||||||
|
HighlightedPosition position= (HighlightedPosition) fPositions.get(i);
|
||||||
|
if (!position.isDeleted())
|
||||||
|
textPresentation.replaceStyleRange(position.createStyleRange());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.ITextInputListener#inputDocumentAboutToBeChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
||||||
|
*/
|
||||||
|
public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
|
||||||
|
setCanceled(true);
|
||||||
|
releaseDocument(oldInput);
|
||||||
|
resetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.ITextInputListener#inputDocumentChanged(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.IDocument)
|
||||||
|
*/
|
||||||
|
public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
|
||||||
|
manageDocument(newInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IDocumentListener#documentAboutToBeChanged(org.eclipse.jface.text.DocumentEvent)
|
||||||
|
*/
|
||||||
|
public void documentAboutToBeChanged(DocumentEvent event) {
|
||||||
|
setCanceled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.IDocumentListener#documentChanged(org.eclipse.jface.text.DocumentEvent)
|
||||||
|
*/
|
||||||
|
public void documentChanged(DocumentEvent event) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns <code>true</code> iff the current reconcile is canceled.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Also called from background thread.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
public boolean isCanceled() {
|
||||||
|
IDocument document= fSourceViewer != null ? fSourceViewer.getDocument() : null;
|
||||||
|
if (document == null)
|
||||||
|
return fIsCanceled;
|
||||||
|
|
||||||
|
synchronized (getLockObject(document)) {
|
||||||
|
return fIsCanceled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether or not the current reconcile is canceled.
|
||||||
|
*
|
||||||
|
* @param isCanceled <code>true</code> iff the current reconcile is canceled
|
||||||
|
*/
|
||||||
|
public void setCanceled(boolean isCanceled) {
|
||||||
|
IDocument document= fSourceViewer != null ? fSourceViewer.getDocument() : null;
|
||||||
|
if (document == null) {
|
||||||
|
fIsCanceled= isCanceled;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (getLockObject(document)) {
|
||||||
|
fIsCanceled= isCanceled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param document the document
|
||||||
|
* @return the document's lock object
|
||||||
|
*/
|
||||||
|
private Object getLockObject(IDocument document) {
|
||||||
|
if (document instanceof ISynchronizable) {
|
||||||
|
Object lock= ((ISynchronizable)document).getLockObject();
|
||||||
|
if (lock != null)
|
||||||
|
return lock;
|
||||||
|
}
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install this presenter on the given source viewer and background presentation
|
||||||
|
* reconciler.
|
||||||
|
*
|
||||||
|
* @param sourceViewer the source viewer
|
||||||
|
* @param backgroundPresentationReconciler the background presentation reconciler,
|
||||||
|
* can be <code>null</code>, in that case {@link SemanticHighlightingPresenter#createPresentation(List, List)}
|
||||||
|
* should not be called
|
||||||
|
*/
|
||||||
|
public void install(CSourceViewer sourceViewer, CPresentationReconciler backgroundPresentationReconciler) {
|
||||||
|
fSourceViewer= sourceViewer;
|
||||||
|
fPresentationReconciler= backgroundPresentationReconciler;
|
||||||
|
|
||||||
|
fSourceViewer.addTextPresentationListener(this);
|
||||||
|
// fSourceViewer.prependTextPresentationListener(this);
|
||||||
|
fSourceViewer.addTextInputListener(this);
|
||||||
|
manageDocument(fSourceViewer.getDocument());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall this presenter.
|
||||||
|
*/
|
||||||
|
public void uninstall() {
|
||||||
|
setCanceled(true);
|
||||||
|
|
||||||
|
if (fSourceViewer != null) {
|
||||||
|
fSourceViewer.removeTextPresentationListener(this);
|
||||||
|
releaseDocument(fSourceViewer.getDocument());
|
||||||
|
invalidateTextPresentation();
|
||||||
|
resetState();
|
||||||
|
|
||||||
|
fSourceViewer.removeTextInputListener(this);
|
||||||
|
fSourceViewer= null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate text presentation of positions with the given highlighting.
|
||||||
|
*
|
||||||
|
* @param highlighting The highlighting
|
||||||
|
*/
|
||||||
|
public void highlightingStyleChanged(HighlightingStyle highlighting) {
|
||||||
|
for (int i= 0, n= fPositions.size(); i < n; i++) {
|
||||||
|
HighlightedPosition position= (HighlightedPosition) fPositions.get(i);
|
||||||
|
if (position.getHighlighting() == highlighting)
|
||||||
|
fSourceViewer.invalidateTextPresentation(position.getOffset(), position.getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate text presentation of all positions.
|
||||||
|
*/
|
||||||
|
private void invalidateTextPresentation() {
|
||||||
|
for (int i= 0, n= fPositions.size(); i < n; i++) {
|
||||||
|
Position position= (Position) fPositions.get(i);
|
||||||
|
fSourceViewer.invalidateTextPresentation(position.getOffset(), position.getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a position with the given range and highlighting unconditionally, only from UI thread.
|
||||||
|
* The position will also be registered on the document. The text presentation is not invalidated.
|
||||||
|
*
|
||||||
|
* @param offset The range offset
|
||||||
|
* @param length The range length
|
||||||
|
* @param highlighting
|
||||||
|
*/
|
||||||
|
private void addPositionFromUI(int offset, int length, HighlightingStyle highlighting) {
|
||||||
|
Position position= createHighlightedPosition(offset, length, highlighting);
|
||||||
|
synchronized (fPositionLock) {
|
||||||
|
insertPosition(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDocument document= fSourceViewer.getDocument();
|
||||||
|
if (document == null)
|
||||||
|
return;
|
||||||
|
String positionCategory= getPositionCategory();
|
||||||
|
try {
|
||||||
|
document.addPosition(positionCategory, position);
|
||||||
|
} catch (BadLocationException e) {
|
||||||
|
// Should not happen
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
} catch (BadPositionCategoryException e) {
|
||||||
|
// Should not happen
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset to initial state.
|
||||||
|
*/
|
||||||
|
private void resetState() {
|
||||||
|
synchronized (fPositionLock) {
|
||||||
|
fPositions.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start managing the given document.
|
||||||
|
*
|
||||||
|
* @param document The document
|
||||||
|
*/
|
||||||
|
private void manageDocument(IDocument document) {
|
||||||
|
if (document != null) {
|
||||||
|
document.addPositionCategory(getPositionCategory());
|
||||||
|
document.addPositionUpdater(fPositionUpdater);
|
||||||
|
document.addDocumentListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop managing the given document.
|
||||||
|
*
|
||||||
|
* @param document The document
|
||||||
|
*/
|
||||||
|
private void releaseDocument(IDocument document) {
|
||||||
|
if (document != null) {
|
||||||
|
document.removeDocumentListener(this);
|
||||||
|
document.removePositionUpdater(fPositionUpdater);
|
||||||
|
try {
|
||||||
|
document.removePositionCategory(getPositionCategory());
|
||||||
|
} catch (BadPositionCategoryException e) {
|
||||||
|
// Should not happen
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return The semantic reconciler position's category.
|
||||||
|
*/
|
||||||
|
private String getPositionCategory() {
|
||||||
|
return toString();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,449 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
import org.eclipse.core.runtime.IStatus;
|
||||||
|
import org.eclipse.core.runtime.Status;
|
||||||
|
import org.eclipse.core.runtime.jobs.Job;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.Position;
|
||||||
|
import org.eclipse.jface.text.Region;
|
||||||
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.jface.text.source.ISourceViewer;
|
||||||
|
import org.eclipse.swt.widgets.Display;
|
||||||
|
import org.eclipse.swt.widgets.Shell;
|
||||||
|
import org.eclipse.ui.IWorkbenchPartSite;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.IPositionConverter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTExpression;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTMacroExpansion;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNodeLocation;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.model.ICElement;
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingManager.HighlightedPosition;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightingManager.HighlightingStyle;
|
||||||
|
import org.eclipse.cdt.internal.ui.text.ICReconcilingListener;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic highlighting reconciler - Background thread implementation.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class SemanticHighlightingReconciler implements ICReconcilingListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects positions from the AST.
|
||||||
|
*/
|
||||||
|
private class PositionCollector extends ASTVisitor {
|
||||||
|
{
|
||||||
|
shouldVisitNames= true;
|
||||||
|
shouldVisitDeclarations= true;
|
||||||
|
shouldVisitExpressions= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The semantic token */
|
||||||
|
private SemanticToken fToken= new SemanticToken();
|
||||||
|
private String fFilePath;
|
||||||
|
private IPositionConverter fPositionTracker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param filePath
|
||||||
|
* @param positionTracker
|
||||||
|
*/
|
||||||
|
public PositionCollector(String filePath, IPositionConverter positionTracker) {
|
||||||
|
fFilePath= filePath;
|
||||||
|
fPositionTracker= positionTracker;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTDeclaration)
|
||||||
|
*/
|
||||||
|
public int visit(IASTDeclaration declaration) {
|
||||||
|
if (!fFilePath.equals(declaration.getContainingFilename())) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTExpression)
|
||||||
|
*/
|
||||||
|
public int visit(IASTExpression expression) {
|
||||||
|
if (!fFilePath.equals(expression.getContainingFilename())) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
IASTNodeLocation[] nodeLocations= expression.getNodeLocations();
|
||||||
|
if (nodeLocations.length > 0 && nodeLocations[0] instanceof IASTMacroExpansion) {
|
||||||
|
if (visitNode(expression)) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.core.dom.ast.ASTVisitor#visit(org.eclipse.cdt.core.dom.ast.IASTName)
|
||||||
|
*/
|
||||||
|
public int visit(IASTName node) {
|
||||||
|
if (!fFilePath.equals(node.getContainingFilename())) {
|
||||||
|
return PROCESS_SKIP;
|
||||||
|
}
|
||||||
|
visitNode(node);
|
||||||
|
return PROCESS_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean visitNode(IASTNode node) {
|
||||||
|
boolean consumed= false;
|
||||||
|
fToken.update(node);
|
||||||
|
for (int i= 0, n= fJobSemanticHighlightings.length; i < n; ++i) {
|
||||||
|
SemanticHighlighting semanticHighlighting= fJobSemanticHighlightings[i];
|
||||||
|
if (fJobHighlightings[i].isEnabled() && semanticHighlighting.consumes(fToken)) {
|
||||||
|
IASTNodeLocation[] nodeLocations= node.getNodeLocations();
|
||||||
|
if (nodeLocations.length > 0) {
|
||||||
|
addNodeLocations(nodeLocations, fJobHighlightings[i]);
|
||||||
|
}
|
||||||
|
consumed= true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fToken.clear();
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all node locations for the given highlighting.
|
||||||
|
*
|
||||||
|
* @param nodeLocations The node locations
|
||||||
|
* @param highlighting The highlighting
|
||||||
|
*/
|
||||||
|
private void addNodeLocations(IASTNodeLocation[] nodeLocations, HighlightingStyle highlighting) {
|
||||||
|
for (int j = 0; j < nodeLocations.length; j++) {
|
||||||
|
IASTNodeLocation nodeLocation = nodeLocations[j];
|
||||||
|
if (nodeLocation instanceof IASTMacroExpansion) {
|
||||||
|
IASTMacroExpansion macroExpansion= (IASTMacroExpansion)nodeLocation;
|
||||||
|
IASTNodeLocation[] expansionLocations = macroExpansion.getExpansionLocations();
|
||||||
|
addNodeLocations(expansionLocations, highlighting);
|
||||||
|
} else {
|
||||||
|
int offset= nodeLocation.getNodeOffset();
|
||||||
|
int length= nodeLocation.getNodeLength();
|
||||||
|
if (fPositionTracker != null) {
|
||||||
|
IRegion actualPos= fPositionTracker.historicToActual(new Region(offset, length));
|
||||||
|
offset= actualPos.getOffset();
|
||||||
|
length= actualPos.getLength();
|
||||||
|
}
|
||||||
|
if (offset > -1 && length > 0) {
|
||||||
|
addPosition(offset, length, highlighting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a position with the given range and highlighting iff it does not exist already.
|
||||||
|
*
|
||||||
|
* @param offset The range offset
|
||||||
|
* @param length The range length
|
||||||
|
* @param highlighting The highlighting
|
||||||
|
*/
|
||||||
|
private void addPosition(int offset, int length, HighlightingStyle highlighting) {
|
||||||
|
boolean isExisting= false;
|
||||||
|
// TODO: use binary search
|
||||||
|
for (int i= 0, n= fRemovedPositions.size(); i < n; i++) {
|
||||||
|
HighlightedPosition position= (HighlightedPosition) fRemovedPositions.get(i);
|
||||||
|
if (position == null)
|
||||||
|
continue;
|
||||||
|
if (position.isEqual(offset, length, highlighting)) {
|
||||||
|
isExisting= true;
|
||||||
|
fRemovedPositions.set(i, null);
|
||||||
|
fNOfRemovedPositions--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isExisting) {
|
||||||
|
Position position= fJobPresenter.createHighlightedPosition(offset, length, highlighting);
|
||||||
|
fAddedPositions.add(position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The C editor this semantic highlighting reconciler is installed on */
|
||||||
|
private CEditor fEditor;
|
||||||
|
/** The semantic highlighting presenter */
|
||||||
|
private SemanticHighlightingPresenter fPresenter;
|
||||||
|
/** Semantic highlightings */
|
||||||
|
private SemanticHighlighting[] fSemanticHighlightings;
|
||||||
|
/** Highlightings */
|
||||||
|
private HighlightingStyle[] fHighlightings;
|
||||||
|
|
||||||
|
/** Background job's added highlighted positions */
|
||||||
|
private List fAddedPositions= new ArrayList();
|
||||||
|
/** Background job's removed highlighted positions */
|
||||||
|
private List fRemovedPositions= new ArrayList();
|
||||||
|
/** Number of removed positions */
|
||||||
|
private int fNOfRemovedPositions;
|
||||||
|
|
||||||
|
/** Background job */
|
||||||
|
private Job fJob;
|
||||||
|
/** Background job lock */
|
||||||
|
private final Object fJobLock= new Object();
|
||||||
|
/** Reconcile operation lock. */
|
||||||
|
private final Object fReconcileLock= new Object();
|
||||||
|
/**
|
||||||
|
* <code>true</code> if any thread is executing
|
||||||
|
* <code>reconcile</code>, <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
private boolean fIsReconciling= false;
|
||||||
|
|
||||||
|
/** The semantic highlighting presenter - cache for background thread, only valid during {@link #reconciled(IASTTranslationUnit, boolean, IProgressMonitor)} */
|
||||||
|
private SemanticHighlightingPresenter fJobPresenter;
|
||||||
|
/** Semantic highlightings - cache for background thread, only valid during {@link #reconciled(IASTTranslationUnit, boolean, IProgressMonitor)} */
|
||||||
|
private SemanticHighlighting[] fJobSemanticHighlightings;
|
||||||
|
/** Highlightings - cache for background thread, only valid during {@link #reconciled(IASTTranslationUnit, boolean, IProgressMonitor)} */
|
||||||
|
private HighlightingStyle[] fJobHighlightings;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.java.ICReconcilingListener#aboutToBeReconciled()
|
||||||
|
*/
|
||||||
|
public void aboutToBeReconciled() {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.cdt.internal.ui.text.ICReconcilingListener#reconciled(IASTTranslationUnit, IPositionConverter, IProgressMonitor)
|
||||||
|
*/
|
||||||
|
public void reconciled(IASTTranslationUnit ast, IPositionConverter positionTracker, IProgressMonitor progressMonitor) {
|
||||||
|
// ensure at most one thread can be reconciling at any time
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
if (fIsReconciling)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
fIsReconciling= true;
|
||||||
|
}
|
||||||
|
fJobPresenter= fPresenter;
|
||||||
|
fJobSemanticHighlightings= fSemanticHighlightings;
|
||||||
|
fJobHighlightings= fHighlightings;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (fJobPresenter == null || fJobSemanticHighlightings == null || fJobHighlightings == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fJobPresenter.setCanceled(progressMonitor != null && progressMonitor.isCanceled());
|
||||||
|
|
||||||
|
if (ast == null || fJobPresenter.isCanceled())
|
||||||
|
return;
|
||||||
|
|
||||||
|
PositionCollector collector= new PositionCollector(ast.getFilePath(), positionTracker);
|
||||||
|
IASTNode[] subtrees= getAffectedSubtrees(ast);
|
||||||
|
if (subtrees.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
startReconcilingPositions();
|
||||||
|
|
||||||
|
if (!fJobPresenter.isCanceled())
|
||||||
|
reconcilePositions(subtrees, collector);
|
||||||
|
|
||||||
|
TextPresentation textPresentation= null;
|
||||||
|
if (!fJobPresenter.isCanceled())
|
||||||
|
textPresentation= fJobPresenter.createPresentation(fAddedPositions, fRemovedPositions);
|
||||||
|
|
||||||
|
if (!fJobPresenter.isCanceled())
|
||||||
|
updatePresentation(textPresentation, fAddedPositions, fRemovedPositions);
|
||||||
|
|
||||||
|
stopReconcilingPositions();
|
||||||
|
} finally {
|
||||||
|
fJobPresenter= null;
|
||||||
|
fJobSemanticHighlightings= null;
|
||||||
|
fJobHighlightings= null;
|
||||||
|
synchronized (fReconcileLock) {
|
||||||
|
fIsReconciling= false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param node Root node
|
||||||
|
* @return Array of subtrees that may be affected by past document changes
|
||||||
|
*/
|
||||||
|
private IASTNode[] getAffectedSubtrees(IASTNode node) {
|
||||||
|
return new IASTNode[] { node };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start reconciling positions.
|
||||||
|
*/
|
||||||
|
private void startReconcilingPositions() {
|
||||||
|
fJobPresenter.addAllPositions(fRemovedPositions);
|
||||||
|
fNOfRemovedPositions= fRemovedPositions.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconcile positions based on the AST subtrees
|
||||||
|
*
|
||||||
|
* @param subtrees the AST subtrees
|
||||||
|
*/
|
||||||
|
private void reconcilePositions(IASTNode[] subtrees, ASTVisitor visitor) {
|
||||||
|
// FIXME: remove positions not covered by subtrees
|
||||||
|
for (int i= 0, n= subtrees.length; i < n; i++) {
|
||||||
|
subtrees[i].accept(visitor);
|
||||||
|
}
|
||||||
|
List oldPositions= fRemovedPositions;
|
||||||
|
List newPositions= new ArrayList(fNOfRemovedPositions);
|
||||||
|
for (int i= 0, n= oldPositions.size(); i < n; i ++) {
|
||||||
|
Object current= oldPositions.get(i);
|
||||||
|
if (current != null)
|
||||||
|
newPositions.add(current);
|
||||||
|
}
|
||||||
|
fRemovedPositions= newPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the presentation.
|
||||||
|
*
|
||||||
|
* @param textPresentation the text presentation
|
||||||
|
* @param addedPositions the added positions
|
||||||
|
* @param removedPositions the removed positions
|
||||||
|
*/
|
||||||
|
private void updatePresentation(TextPresentation textPresentation, List addedPositions, List removedPositions) {
|
||||||
|
Runnable runnable= fJobPresenter.createUpdateRunnable(textPresentation, addedPositions, removedPositions);
|
||||||
|
if (runnable == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CEditor editor= fEditor;
|
||||||
|
if (editor == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IWorkbenchPartSite site= editor.getSite();
|
||||||
|
if (site == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Shell shell= site.getShell();
|
||||||
|
if (shell == null || shell.isDisposed())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Display display= shell.getDisplay();
|
||||||
|
if (display == null || display.isDisposed())
|
||||||
|
return;
|
||||||
|
|
||||||
|
display.asyncExec(runnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop reconciling positions.
|
||||||
|
*/
|
||||||
|
private void stopReconcilingPositions() {
|
||||||
|
fRemovedPositions.clear();
|
||||||
|
fNOfRemovedPositions= 0;
|
||||||
|
fAddedPositions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Install this reconciler on the given editor, presenter and highlightings.
|
||||||
|
* @param editor the editor
|
||||||
|
* @param sourceViewer the source viewer
|
||||||
|
* @param presenter the semantic highlighting presenter
|
||||||
|
* @param semanticHighlightings the semantic highlightings
|
||||||
|
* @param highlightings the highlightings
|
||||||
|
*/
|
||||||
|
public void install(CEditor editor, ISourceViewer sourceViewer, SemanticHighlightingPresenter presenter, SemanticHighlighting[] semanticHighlightings, HighlightingStyle[] highlightings) {
|
||||||
|
fPresenter= presenter;
|
||||||
|
fSemanticHighlightings= semanticHighlightings;
|
||||||
|
fHighlightings= highlightings;
|
||||||
|
|
||||||
|
fEditor= editor;
|
||||||
|
|
||||||
|
if (fEditor != null) {
|
||||||
|
fEditor.addReconcileListener(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uninstall this reconciler from the editor
|
||||||
|
*/
|
||||||
|
public void uninstall() {
|
||||||
|
if (fPresenter != null)
|
||||||
|
fPresenter.setCanceled(true);
|
||||||
|
|
||||||
|
if (fEditor != null) {
|
||||||
|
fEditor.removeReconcileListener(this);
|
||||||
|
fEditor= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
fSemanticHighlightings= null;
|
||||||
|
fHighlightings= null;
|
||||||
|
fPresenter= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule a background job for retrieving the AST and reconciling the Semantic Highlighting model.
|
||||||
|
*/
|
||||||
|
private void scheduleJob() {
|
||||||
|
final ICElement element= fEditor.getInputCElement();
|
||||||
|
|
||||||
|
synchronized (fJobLock) {
|
||||||
|
final Job oldJob= fJob;
|
||||||
|
if (fJob != null) {
|
||||||
|
fJob.cancel();
|
||||||
|
fJob= null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (element != null) {
|
||||||
|
fJob= new Job(CEditorMessages.getString("SemanticHighlighting_job")) { //$NON-NLS-1$
|
||||||
|
protected IStatus run(IProgressMonitor monitor) {
|
||||||
|
if (oldJob != null) {
|
||||||
|
try {
|
||||||
|
oldJob.join();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
CUIPlugin.getDefault().log(e);
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (monitor.isCanceled())
|
||||||
|
return Status.CANCEL_STATUS;
|
||||||
|
IASTTranslationUnit ast= CUIPlugin.getDefault().getASTProvider().getAST(element, ASTProvider.WAIT_YES, monitor);
|
||||||
|
reconciled(ast, null, monitor);
|
||||||
|
synchronized (fJobLock) {
|
||||||
|
// allow the job to be gc'ed
|
||||||
|
if (fJob == this)
|
||||||
|
fJob= null;
|
||||||
|
}
|
||||||
|
return Status.OK_STATUS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// fJob.setSystem(true);
|
||||||
|
fJob.setPriority(Job.DECORATE);
|
||||||
|
fJob.schedule();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refreshes the highlighting.
|
||||||
|
*/
|
||||||
|
public void refresh() {
|
||||||
|
scheduleJob();
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,99 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.editor;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Semantic token.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public final class SemanticToken {
|
||||||
|
|
||||||
|
/** AST node */
|
||||||
|
private IASTNode fNode;
|
||||||
|
|
||||||
|
/** Binding */
|
||||||
|
private IBinding fBinding;
|
||||||
|
/** Is the binding resolved? */
|
||||||
|
private boolean fIsBindingResolved= false;
|
||||||
|
|
||||||
|
/** AST root */
|
||||||
|
private IASTTranslationUnit fRoot;
|
||||||
|
private boolean fIsRootResolved= false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the binding, can be <code>null</code>.
|
||||||
|
*/
|
||||||
|
public IBinding getBinding() {
|
||||||
|
if (!fIsBindingResolved) {
|
||||||
|
fIsBindingResolved= true;
|
||||||
|
if (fNode instanceof IASTName)
|
||||||
|
fBinding= ((IASTName)fNode).resolveBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
return fBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the AST node
|
||||||
|
*/
|
||||||
|
public IASTNode getNode() {
|
||||||
|
return fNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the AST root
|
||||||
|
*/
|
||||||
|
public IASTTranslationUnit getRoot() {
|
||||||
|
if (!fIsRootResolved) {
|
||||||
|
fIsRootResolved= true;
|
||||||
|
if (fNode != null) {
|
||||||
|
fRoot= fNode.getTranslationUnit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fRoot;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update this token with the given AST node.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Allowed to be used by {@link SemanticHighlightingReconciler} only.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param node the AST node
|
||||||
|
*/
|
||||||
|
void update(IASTNode node) {
|
||||||
|
clear();
|
||||||
|
fNode= node;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears this token.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Allowed to be used by {@link SemanticHighlightingReconciler} only.
|
||||||
|
* </p>
|
||||||
|
*/
|
||||||
|
void clear() {
|
||||||
|
fNode= null;
|
||||||
|
fBinding= null;
|
||||||
|
fIsBindingResolved= false;
|
||||||
|
fRoot= null;
|
||||||
|
fIsRootResolved= false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,167 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2005 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
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.preferences;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||||
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
|
import org.eclipse.jface.preference.PreferencePage;
|
||||||
|
import org.eclipse.swt.SWT;
|
||||||
|
import org.eclipse.swt.layout.GridData;
|
||||||
|
import org.eclipse.swt.layout.GridLayout;
|
||||||
|
import org.eclipse.swt.widgets.Button;
|
||||||
|
import org.eclipse.swt.widgets.Composite;
|
||||||
|
import org.eclipse.swt.widgets.Control;
|
||||||
|
import org.eclipse.swt.widgets.Label;
|
||||||
|
import org.eclipse.swt.widgets.Text;
|
||||||
|
import org.eclipse.ui.IWorkbench;
|
||||||
|
import org.eclipse.ui.IWorkbenchPreferencePage;
|
||||||
|
import org.eclipse.ui.PlatformUI;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.ui.CUIPlugin;
|
||||||
|
import org.eclipse.cdt.ui.PreferenceConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Preference page for work in progress.
|
||||||
|
*/
|
||||||
|
public class WorkInProgressPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
|
||||||
|
|
||||||
|
private List fCheckBoxes;
|
||||||
|
private List fRadioButtons;
|
||||||
|
private List fTextControls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* creates a new preference page.
|
||||||
|
*/
|
||||||
|
public WorkInProgressPreferencePage() {
|
||||||
|
setPreferenceStore(getPreferenceStore());
|
||||||
|
fRadioButtons= new ArrayList();
|
||||||
|
fCheckBoxes= new ArrayList();
|
||||||
|
fTextControls= new ArrayList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Button addCheckBox(Composite parent, String label, String key) {
|
||||||
|
GridData gd= new GridData(GridData.HORIZONTAL_ALIGN_FILL);
|
||||||
|
|
||||||
|
Button button= new Button(parent, SWT.CHECK);
|
||||||
|
button.setText(label);
|
||||||
|
button.setData(key);
|
||||||
|
button.setLayoutData(gd);
|
||||||
|
|
||||||
|
button.setSelection(getPreferenceStore().getBoolean(key));
|
||||||
|
|
||||||
|
fCheckBoxes.add(button);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see PreferencePage#createControl(Composite)
|
||||||
|
*/
|
||||||
|
public void createControl(Composite parent) {
|
||||||
|
super.createControl(parent);
|
||||||
|
PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), "WORK_IN_PROGRESS_PREFERENCE_PAGE"); //$NON-NLS-1$
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Control createContents(Composite parent) {
|
||||||
|
initializeDialogUnits(parent);
|
||||||
|
|
||||||
|
Composite result= new Composite(parent, SWT.NONE);
|
||||||
|
GridLayout layout= new GridLayout();
|
||||||
|
layout.marginHeight= convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
|
||||||
|
layout.marginWidth= 0;
|
||||||
|
layout.verticalSpacing= convertVerticalDLUsToPixels(10);
|
||||||
|
layout.horizontalSpacing= convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
|
||||||
|
result.setLayout(layout);
|
||||||
|
|
||||||
|
// Add your controls here
|
||||||
|
addCheckBox(result, "Semantic Highlighting", PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED); //$NON-NLS-1$
|
||||||
|
applyDialogFont(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
|
||||||
|
*/
|
||||||
|
public void init(IWorkbench workbench) {
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void createSpacer(Composite composite, int columnSpan) {
|
||||||
|
Label label= new Label(composite, SWT.NONE);
|
||||||
|
GridData gd= new GridData();
|
||||||
|
gd.horizontalSpan= columnSpan;
|
||||||
|
label.setLayoutData(gd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.preference.PreferencePage#doGetPreferenceStore()
|
||||||
|
*/
|
||||||
|
protected IPreferenceStore doGetPreferenceStore() {
|
||||||
|
return CUIPlugin.getDefault().getPreferenceStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see PreferencePage#performDefaults()
|
||||||
|
*/
|
||||||
|
protected void performDefaults() {
|
||||||
|
IPreferenceStore store= getPreferenceStore();
|
||||||
|
for (int i= 0; i < fCheckBoxes.size(); i++) {
|
||||||
|
Button button= (Button) fCheckBoxes.get(i);
|
||||||
|
String key= (String) button.getData();
|
||||||
|
button.setSelection(store.getDefaultBoolean(key));
|
||||||
|
}
|
||||||
|
for (int i= 0; i < fRadioButtons.size(); i++) {
|
||||||
|
Button button= (Button) fRadioButtons.get(i);
|
||||||
|
String[] info= (String[]) button.getData();
|
||||||
|
button.setSelection(info[1].equals(store.getDefaultString(info[0])));
|
||||||
|
}
|
||||||
|
for (int i= 0; i < fTextControls.size(); i++) {
|
||||||
|
Text text= (Text) fTextControls.get(i);
|
||||||
|
String key= (String) text.getData();
|
||||||
|
text.setText(store.getDefaultString(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
super.performDefaults();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see IPreferencePage#performOk()
|
||||||
|
*/
|
||||||
|
public boolean performOk() {
|
||||||
|
IPreferenceStore store= getPreferenceStore();
|
||||||
|
for (int i= 0; i < fCheckBoxes.size(); i++) {
|
||||||
|
Button button= (Button) fCheckBoxes.get(i);
|
||||||
|
String key= (String) button.getData();
|
||||||
|
store.setValue(key, button.getSelection());
|
||||||
|
}
|
||||||
|
for (int i= 0; i < fRadioButtons.size(); i++) {
|
||||||
|
Button button= (Button) fRadioButtons.get(i);
|
||||||
|
if (button.getSelection()) {
|
||||||
|
String[] info= (String[]) button.getData();
|
||||||
|
store.setValue(info[0], info[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i= 0; i < fTextControls.size(); i++) {
|
||||||
|
Text text= (Text) fTextControls.get(i);
|
||||||
|
String key= (String) text.getData();
|
||||||
|
store.setValue(key, text.getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
CUIPlugin.getDefault().savePluginPreferences();
|
||||||
|
return super.performOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initDefaults(IPreferenceStore store) {
|
||||||
|
// Initialize your defaults here
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
import org.eclipse.jface.text.IDocument;
|
||||||
|
import org.eclipse.jface.text.IRegion;
|
||||||
|
import org.eclipse.jface.text.TextPresentation;
|
||||||
|
import org.eclipse.jface.text.presentation.PresentationReconciler;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Presentation reconciler, adding functionality for operation without a viewer.
|
||||||
|
* Cloned from JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public class CPresentationReconciler extends PresentationReconciler {
|
||||||
|
|
||||||
|
/** Last used document */
|
||||||
|
private IDocument fLastDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a "repair description" for the given damage and returns
|
||||||
|
* this description as a text presentation.
|
||||||
|
* <p>
|
||||||
|
* NOTE: Should not be used if this reconciler is installed on a viewer.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param damage the damage to be repaired
|
||||||
|
* @param document the document whose presentation must be repaired
|
||||||
|
* @return the presentation repair description as text presentation
|
||||||
|
*/
|
||||||
|
public TextPresentation createRepairDescription(IRegion damage, IDocument document) {
|
||||||
|
if (document != fLastDocument) {
|
||||||
|
setDocumentToDamagers(document);
|
||||||
|
setDocumentToRepairers(document);
|
||||||
|
fLastDocument= document;
|
||||||
|
}
|
||||||
|
return createPresentation(damage, document);
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Corporation - initial API and implementation
|
* IBM Corporation - initial API and implementation
|
||||||
* QNX Software System
|
* QNX Software System
|
||||||
|
* Anton Leherbauer (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
@ -24,15 +25,18 @@ import org.eclipse.jface.text.IDocument;
|
||||||
import org.eclipse.jface.text.IRegion;
|
import org.eclipse.jface.text.IRegion;
|
||||||
import org.eclipse.jface.text.reconciler.DirtyRegion;
|
import org.eclipse.jface.text.reconciler.DirtyRegion;
|
||||||
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
|
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
|
||||||
|
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
|
||||||
import org.eclipse.ui.texteditor.ITextEditor;
|
import org.eclipse.ui.texteditor.ITextEditor;
|
||||||
|
|
||||||
|
|
||||||
public class CReconcilingStrategy implements IReconcilingStrategy {
|
public class CReconcilingStrategy implements IReconcilingStrategy, IReconcilingStrategyExtension {
|
||||||
|
|
||||||
private ITextEditor fEditor;
|
private ITextEditor fEditor;
|
||||||
private IWorkingCopyManager fManager;
|
private IWorkingCopyManager fManager;
|
||||||
private IProgressMonitor fProgressMonitor;
|
private IProgressMonitor fProgressMonitor;
|
||||||
private String txt = null;
|
private String txt = null;
|
||||||
|
// used by tests
|
||||||
|
protected boolean fInitialProcessDone;
|
||||||
|
|
||||||
public CReconcilingStrategy(CEditor editor) {
|
public CReconcilingStrategy(CEditor editor) {
|
||||||
fEditor= editor;
|
fEditor= editor;
|
||||||
|
@ -123,5 +127,16 @@ public class CReconcilingStrategy implements IReconcilingStrategy {
|
||||||
} catch(CModelException e) {
|
} catch(CModelException e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @see org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension#initialReconcile()
|
||||||
|
*/
|
||||||
|
public void initialReconcile() {
|
||||||
|
if (fEditor instanceof IReconcilingParticipant) {
|
||||||
|
IReconcilingParticipant p= (IReconcilingParticipant) fEditor;
|
||||||
|
p.reconciled(true);
|
||||||
|
}
|
||||||
|
fInitialProcessDone= true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* IBM Corporation - initial API and implementation
|
* IBM Corporation - initial API and implementation
|
||||||
* QNX Software System
|
* QNX Software System
|
||||||
|
* Anton Leherbauer (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.ui.text;
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
@ -33,7 +34,6 @@ import org.eclipse.jface.text.information.IInformationPresenter;
|
||||||
import org.eclipse.jface.text.information.IInformationProvider;
|
import org.eclipse.jface.text.information.IInformationProvider;
|
||||||
import org.eclipse.jface.text.information.InformationPresenter;
|
import org.eclipse.jface.text.information.InformationPresenter;
|
||||||
import org.eclipse.jface.text.presentation.IPresentationReconciler;
|
import org.eclipse.jface.text.presentation.IPresentationReconciler;
|
||||||
import org.eclipse.jface.text.presentation.PresentationReconciler;
|
|
||||||
import org.eclipse.jface.text.reconciler.IReconciler;
|
import org.eclipse.jface.text.reconciler.IReconciler;
|
||||||
import org.eclipse.jface.text.reconciler.MonoReconciler;
|
import org.eclipse.jface.text.reconciler.MonoReconciler;
|
||||||
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
|
import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
|
||||||
|
@ -163,7 +163,7 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
|
||||||
*/
|
*/
|
||||||
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
|
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {
|
||||||
|
|
||||||
PresentationReconciler reconciler= new PresentationReconciler();
|
CPresentationReconciler reconciler= new CPresentationReconciler();
|
||||||
reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
|
reconciler.setDocumentPartitioning(getConfiguredDocumentPartitioning(sourceViewer));
|
||||||
|
|
||||||
RuleBasedScanner scanner = null;
|
RuleBasedScanner scanner = null;
|
||||||
|
@ -529,5 +529,14 @@ public class CSourceViewerConfiguration extends TextSourceViewerConfiguration {
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapt to the given preference change event.
|
||||||
|
*
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
|
public void handlePropertyChangeEvent(PropertyChangeEvent event) {
|
||||||
|
fTextTools.adaptToPreferenceChange(event);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2000, 2006 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
|
||||||
|
* Anton Leherbauer (Wind River Systems) - Adapted for CDT
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.ui.text;
|
||||||
|
|
||||||
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.IPositionConverter;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface of an object listening to (AST-) reconciling.
|
||||||
|
* Inspired by JDT.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public interface ICReconcilingListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called before reconciling is started.
|
||||||
|
*/
|
||||||
|
void aboutToBeReconciled();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called after reconciling has been finished.
|
||||||
|
*
|
||||||
|
* @param ast
|
||||||
|
* the translation unit AST or <code>null</code> if the working
|
||||||
|
* copy was consistent or reconciliation has been cancelled
|
||||||
|
* @param positionTracker
|
||||||
|
* the position tracker to map AST positions to current document
|
||||||
|
* positions; may be <code>null</code> which means positions
|
||||||
|
* can be considered up-to-date
|
||||||
|
* @param progressMonitor
|
||||||
|
* the progress monitor
|
||||||
|
*/
|
||||||
|
void reconciled(IASTTranslationUnit ast, IPositionConverter positionTracker, IProgressMonitor progressMonitor);
|
||||||
|
}
|
|
@ -68,6 +68,7 @@ import org.eclipse.cdt.internal.ui.ICStatusConstants;
|
||||||
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
import org.eclipse.cdt.internal.ui.IContextMenuConstants;
|
||||||
import org.eclipse.cdt.internal.ui.ResourceAdapterFactory;
|
import org.eclipse.cdt.internal.ui.ResourceAdapterFactory;
|
||||||
import org.eclipse.cdt.internal.ui.buildconsole.BuildConsoleManager;
|
import org.eclipse.cdt.internal.ui.buildconsole.BuildConsoleManager;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.ASTProvider;
|
||||||
import org.eclipse.cdt.internal.ui.editor.CDocumentProvider;
|
import org.eclipse.cdt.internal.ui.editor.CDocumentProvider;
|
||||||
import org.eclipse.cdt.internal.ui.editor.CustomBufferFactory;
|
import org.eclipse.cdt.internal.ui.editor.CustomBufferFactory;
|
||||||
import org.eclipse.cdt.internal.ui.editor.ExternalSearchDocumentProvider;
|
import org.eclipse.cdt.internal.ui.editor.ExternalSearchDocumentProvider;
|
||||||
|
@ -110,9 +111,8 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
private CEditorTextHoverDescriptor[] fCEditorTextHoverDescriptors;
|
private CEditorTextHoverDescriptor[] fCEditorTextHoverDescriptors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The extension point registry for the <code>org.eclipse.jdt.ui.javaFoldingStructureProvider</code>
|
* The extension point registry for the <code>org.eclipse.cdt.ui.foldingStructureProviders</code>
|
||||||
* extension point.
|
* extension point.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
private CFoldingStructureProviderRegistry fFoldingStructureProviderRegistry;
|
private CFoldingStructureProviderRegistry fFoldingStructureProviderRegistry;
|
||||||
|
|
||||||
|
@ -338,17 +338,23 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
private CElementAdapterFactory fCElementAdapterFactory;
|
private CElementAdapterFactory fCElementAdapterFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The template context type registry for the java editor.
|
* The template context type registry for the C editor.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
private ContributionContextTypeRegistry fContextTypeRegistry;
|
private ContributionContextTypeRegistry fContextTypeRegistry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The template store for the java editor.
|
* The template store for the C editor.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
private TemplateStore fTemplateStore;
|
private TemplateStore fTemplateStore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The AST provider.
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
private ASTProvider fASTProvider;
|
||||||
|
|
||||||
|
|
||||||
public CUIPlugin() {
|
public CUIPlugin() {
|
||||||
fgCPlugin = this;
|
fgCPlugin = this;
|
||||||
|
@ -708,9 +714,9 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the template context type registry for the java plugin.
|
* Returns the template context type registry for the C plugin.
|
||||||
*
|
*
|
||||||
* @return the template context type registry for the java plugin
|
* @return the template context type registry for the C plugin
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public ContextTypeRegistry getTemplateContextRegistry() {
|
public ContextTypeRegistry getTemplateContextRegistry() {
|
||||||
|
@ -722,9 +728,9 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the template store for the java editor templates.
|
* Returns the template store for the C editor templates.
|
||||||
*
|
*
|
||||||
* @return the template store for the java editor templates
|
* @return the template store for the C editor templates
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public TemplateStore getTemplateStore() {
|
public TemplateStore getTemplateStore() {
|
||||||
|
@ -739,4 +745,17 @@ public class CUIPlugin extends AbstractUIPlugin {
|
||||||
return fTemplateStore;
|
return fTemplateStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the AST provider.
|
||||||
|
*
|
||||||
|
* @return the AST provider
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public synchronized ASTProvider getASTProvider() {
|
||||||
|
if (fASTProvider == null)
|
||||||
|
fASTProvider= new ASTProvider();
|
||||||
|
|
||||||
|
return fASTProvider;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,14 @@
|
||||||
package org.eclipse.cdt.ui;
|
package org.eclipse.cdt.ui;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.cview.CView;
|
import org.eclipse.cdt.internal.ui.cview.CView;
|
||||||
|
import org.eclipse.cdt.internal.ui.editor.SemanticHighlightings;
|
||||||
import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage;
|
import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage;
|
||||||
import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage;
|
import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage;
|
||||||
import org.eclipse.cdt.internal.ui.preferences.CParserPreferencePage;
|
import org.eclipse.cdt.internal.ui.preferences.CParserPreferencePage;
|
||||||
import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;
|
import org.eclipse.cdt.internal.ui.preferences.CPluginPreferencePage;
|
||||||
import org.eclipse.cdt.internal.ui.preferences.CodeAssistPreferencePage;
|
import org.eclipse.cdt.internal.ui.preferences.CodeAssistPreferencePage;
|
||||||
|
import org.eclipse.cdt.internal.ui.preferences.WorkInProgressPreferencePage;
|
||||||
|
|
||||||
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
|
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.ui.editors.text.EditorsUI;
|
import org.eclipse.ui.editors.text.EditorsUI;
|
||||||
|
@ -41,7 +44,9 @@ public class CUIPreferenceInitializer extends AbstractPreferenceInitializer {
|
||||||
CParserPreferencePage.initDefaults(store);
|
CParserPreferencePage.initDefaults(store);
|
||||||
CEditorPreferencePage.initDefaults(store);
|
CEditorPreferencePage.initDefaults(store);
|
||||||
CodeAssistPreferencePage.initDefaults(store);
|
CodeAssistPreferencePage.initDefaults(store);
|
||||||
|
SemanticHighlightings.initDefaults(store);
|
||||||
|
WorkInProgressPreferencePage.initDefaults(store);
|
||||||
|
|
||||||
// We need to do this remove any keys that might have been
|
// We need to do this remove any keys that might have been
|
||||||
// in the CUIPlugin store prior to the move of the CEditor setting
|
// in the CUIPlugin store prior to the move of the CEditor setting
|
||||||
// All of those settings are now in the workbench "All TextEditor" preference Page.
|
// All of those settings are now in the workbench "All TextEditor" preference Page.
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
package org.eclipse.cdt.ui;
|
package org.eclipse.cdt.ui;
|
||||||
|
|
||||||
import org.eclipse.cdt.internal.ui.text.ICColorConstants;
|
import org.eclipse.cdt.internal.ui.text.ICColorConstants;
|
||||||
|
|
||||||
import org.eclipse.jface.action.Action;
|
import org.eclipse.jface.action.Action;
|
||||||
import org.eclipse.jface.preference.IPreferenceStore;
|
import org.eclipse.jface.preference.IPreferenceStore;
|
||||||
import org.eclipse.jface.preference.PreferenceConverter;
|
import org.eclipse.jface.preference.PreferenceConverter;
|
||||||
|
@ -432,6 +433,86 @@ public class PreferenceConstants {
|
||||||
*/
|
*/
|
||||||
public static final String EDITOR_SHOW_TEXT_HOVER_AFFORDANCE= "PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE"; //$NON-NLS-1$
|
public static final String EDITOR_SHOW_TEXT_HOVER_AFFORDANCE= "PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference prefix for semantic highlighting preferences.
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX="semanticHighlighting."; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls a semantic highlighting's color.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>String</code>. A RGB color value encoded as a string
|
||||||
|
* using class <code>PreferenceConverter</code>
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @see org.eclipse.jface.resource.StringConverter
|
||||||
|
* @see org.eclipse.jface.preference.PreferenceConverter
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_COLOR_SUFFIX=".color"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls if semantic highlighting has the text attribute bold.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if bold.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_BOLD_SUFFIX=".bold"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls if semantic highlighting has the text attribute italic.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if italic.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_ITALIC_SUFFIX=".italic"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls if semantic highlighting has the text attribute strikethrough.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if strikethrough.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_STRIKETHROUGH_SUFFIX=".strikethrough"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls if semantic highlighting has the text attribute underline.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if underline.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_UNDERLINE_SUFFIX=".underline"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference suffix that controls if semantic highlighting is enabled.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if enabled.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED_SUFFIX=".enabled"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A named preference key that controls if semantic highlighting is enabled.
|
||||||
|
* <p>
|
||||||
|
* Value is of type <code>Boolean</code>: <code>true</code> if enabled.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @since 4.0
|
||||||
|
*/
|
||||||
|
public static final String EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED= "semanticHighlighting.enabled"; //$NON-NLS-1$
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the given preference store with the default values.
|
* Initializes the given preference store with the default values.
|
||||||
|
|
Loading…
Add table
Reference in a new issue