Bug 536201 Add a highlighting for enum classes

Change-Id: I6b16efbbb268f9fdc4a884e96c30192dd64c5db1
Signed-off-by: Bassem Girgis <brgirgis@gmail.com>
diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java
index 7ef4f2c..0314b62 100644
--- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java
+++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/SemanticHighlightingTest.java
@@ -81,7 +81,7 @@
 	private IASTTranslationUnit fAST;
 	
 	// The highlighted positions stored in the document don't store any information
-	// that directly identifies which highligting they are for. To recover this
+	// that directly identifies which highlighting they are for. To recover this
 	// information, we assign a different color to each highlighting, and then
 	// look up the highlighting's preference key based on the color.
 	private Map<RGB, String> fColorToPreferenceKeyMap;
@@ -260,7 +260,7 @@
 
 	//  void SDKFunction();
 	//	class SDKClass { public: void SDKMethod(); };\n\n";
-	
+
 	//#define INT      int                               //$macroDefinition
 	//#define FUNCTION_MACRO(arg) globalFunc(arg)        //$macroDefinition
 	//#define EMPTY_MACRO(arg)                           //$macroDefinition
@@ -430,6 +430,30 @@
 	public void testVariousHighlightings() throws Exception {
 		makeAssertions();
 	}
+
+	//enum class EnumerationClass {                      //$enumClass
+	//    enumerator                                     //$enumerator
+	//};
+	//
+	//class Base1 {};                                    //$class
+	//class Base2 {};                                    //$class
+	//
+	//class ClassContainer : Base1, Base2 {              //$class,class,class
+	//    
+	//public:
+	//    enum class pubEnumerationClass {pubEnum};      //$enumClass,enumerator
+	//    
+	//protected:
+	//    enum class protEnumerationClass {protEnum};    //$enumClass,enumerator
+	//    
+	//private:
+	//    enum class privEnumerationClass {privEnum};    //$enumClass,enumerator
+	//
+	//};
+	//
+	public void testEnumClassHighlightings() throws Exception {
+		makeAssertions();
+	}
 	
     //  class C {                                        //$class
     //    template <typename T> void bar(T);             //$templateParameter,methodDeclaration,templateParameter
@@ -488,12 +512,17 @@
     //	namespace N {                                    //$namespace
     //		class C {                                    //$class
     //			enum E1 {};                              //$enum
+    //			enum class EC1 {};                       //$enumClass
     //		};
     //		C::E1 e1;                                    //$class,enum,globalVariable
+    //		C::EC1 ec1;                                  //$class,enumClass,globalVariable
     //		enum E2 {};                                  //$enum
+    //		enum class EC2 {};                           //$enumClass
     //	}
     //	N::C::E1 e1;                                     //$namespace,class,enum,globalVariable
+    //	N::C::EC1 ec1;                                   //$namespace,class,enumClass,globalVariable
     //	N::E2 e2;                                        //$namespace,enum,globalVariable
+    //	N::EC2 ec2;                                      //$namespace,enumClass,globalVariable
     public void testQualifiedEnum_485709() throws Exception {
     	makeAssertions();
     }
@@ -517,14 +546,14 @@
     //	template <typename T>                            //$templateParameter
     //	struct Base {                                    //$class
     //		enum E { A };                                //$enum,enumerator
-    //		enum class F { B };                          //$enum,enumerator
+    //		enum class F { B };                          //$enumClass,enumerator
     //	};
     //	template <typename T>                            //$templateParameter
     //	struct Derived : Base<T> {                       //$class,class,templateParameter
     //		static typename Base<T>::E x                 //$class,templateParameter,enum,staticField
     //          = Base<T>::A;                            //$class,templateParameter,enumerator
-    //		static typename Base<T>::F y                 //$class,templateParameter,enum,staticField
-    //          = Base<T>::F::B;                         //$class,templateParameter,enum,enumerator
+    //		static typename Base<T>::F y                 //$class,templateParameter,enumClass,staticField
+    //          = Base<T>::F::B;                         //$class,templateParameter,enumClass,enumerator
     //	};
     public void testDependentEnum_486688() throws Exception {
     	makeAssertions();
diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml
index 5ceb7c9..b112960 100644
--- a/core/org.eclipse.cdt.ui/plugin.xml
+++ b/core/org.eclipse.cdt.ui/plugin.xml
@@ -836,6 +836,12 @@
             value="100, 70, 50">
       </colorDefinition>
       <colorDefinition
+            id="org.eclipse.cdt.ui.enumClassHighlighting"
+            isEditable="false"
+            label="%Dummy.label"
+            value="0, 80, 50">
+      </colorDefinition>
+      <colorDefinition
             id="org.eclipse.cdt.ui.macroSubstitutionHighlighting"
             isEditable="false"
             label="%Dummy.label"
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
index 7875844..ae53fc6 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.java
@@ -94,6 +94,7 @@
 	public static String SemanticHighlighting_method;
 	public static String SemanticHighlighting_classes;
 	public static String SemanticHighlighting_enums;
+	public static String SemanticHighlighting_enumClasses;
 	public static String SemanticHighlighting_enumerator;
 	public static String SemanticHighlighting_templateArguments;
 	public static String SemanticHighlighting_templateParameter;
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
index b632ad1..01be0cd 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditorMessages.properties
@@ -91,6 +91,7 @@
 SemanticHighlighting_method= Methods
 SemanticHighlighting_classes= Classes, Structs, Unions
 SemanticHighlighting_enums= Enums
+SemanticHighlighting_enumClasses= Enum Classes
 SemanticHighlighting_enumerator= Enumerators
 SemanticHighlighting_templateArguments= Template arguments
 SemanticHighlighting_templateParameter= Template parameters
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
index f821724..7bb05d8 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/SemanticHighlightings.java
@@ -76,6 +76,7 @@
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
 import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
 import org.eclipse.cdt.core.dom.ast.cpp.SemanticQueries;
 import org.eclipse.cdt.core.index.IIndex;
@@ -177,6 +178,11 @@
 	public static final String ENUM= "enum"; //$NON-NLS-1$
 
 	/**
+	 * A named preference part that controls the highlighting of enum classes.
+	 */
+	public static final String ENUM_CLASS= "enumClass"; //$NON-NLS-1$
+
+	/**
 	 * A named preference part that controls the highlighting of macro references.
 	 */
 	public static final String MACRO_REFERENCE= "macroSubstitution"; //$NON-NLS-1$
@@ -343,7 +349,7 @@
 				IBinding binding= token.getBinding();
 				if (binding instanceof IField) {
 					if (binding instanceof ICPPUnknownBinding) {
-						if (heuristicallyResolvesToEnumerator((ICPPUnknownBinding) binding)) {
+						if (heuristicallyResolve((ICPPUnknownBinding) binding) instanceof IEnumerator) {
 							return false;
 						}
 					}
@@ -1065,7 +1071,7 @@
 				IBinding binding= token.getBinding();
 				if (binding instanceof ICompositeType && !(binding instanceof ICPPTemplateParameter)) {
 					if (binding instanceof ICPPUnknownBinding) {
-						if (heuristicallyResolvesToEnumeration((ICPPUnknownBinding) binding)) {
+						if (heuristicallyResolve((ICPPUnknownBinding) binding) instanceof IEnumeration) {
 							return false;
 						}
 					}
@@ -1118,13 +1124,67 @@
 					return false;
 				}
 				IBinding binding= token.getBinding();
+				if (binding instanceof ICPPUnknownBinding) {
+					binding= heuristicallyResolve((ICPPUnknownBinding) binding);
+				}
 				if (binding instanceof IEnumeration) {
+					if (binding instanceof ICPPEnumeration) {
+						return !((ICPPEnumeration) binding).isScoped();
+					}
 					return true;
 				}
+			}
+			return false;
+		}
+	}
+
+	/**
+	 * Semantic highlighting for enum classes.
+	 */
+	private static final class EnumClassHighlighting extends SemanticHighlightingWithOwnPreference {
+		@Override
+		public String getPreferenceKey() {
+			return ENUM_CLASS;
+		}
+
+		@Override
+		public RGB getDefaultDefaultTextColor() {
+			return new RGB(0, 80, 50);
+		}
+
+		@Override
+		public boolean isBoldByDefault() {
+			return false;
+		}
+
+		@Override
+		public boolean isItalicByDefault() {
+			return false;
+		}
+
+		@Override
+		public boolean isEnabledByDefault() {
+			return true;
+		}
+
+		@Override
+		public String getDisplayName() {
+			return CEditorMessages.SemanticHighlighting_enumClasses;
+		}
+
+		@Override
+		public boolean consumes(ISemanticToken token) {
+			IASTNode node= token.getNode();
+			if (node instanceof IASTName) {
+				if (node instanceof ICPPASTQualifiedName) {
+					return false;
+				}
+				IBinding binding= token.getBinding();
 				if (binding instanceof ICPPUnknownBinding) {
-					if (heuristicallyResolvesToEnumeration((ICPPUnknownBinding) binding)) {
-						return true;
-					}
+					binding= heuristicallyResolve((ICPPUnknownBinding) binding);
+				}
+				if (binding instanceof ICPPEnumeration) {
+					return ((ICPPEnumeration) binding).isScoped();
 				}
 			}
 			return false;
@@ -1419,14 +1479,12 @@
 					return false;
 				}
 				IBinding binding= token.getBinding();
+				if (binding instanceof ICPPUnknownBinding) {
+					binding= heuristicallyResolve((ICPPUnknownBinding) binding);
+				}
 				if (binding instanceof IEnumerator) {
 					return true;
 				}
-				if (binding instanceof ICPPUnknownBinding) {
-					if (heuristicallyResolvesToEnumerator((ICPPUnknownBinding) binding)) {
-						return true;
-					}
-				}
 			}
 			return false;
 		}
@@ -1852,14 +1910,12 @@
 		}
 	}
 
-	private static boolean heuristicallyResolvesToEnumeration(ICPPUnknownBinding binding) {
+	private static IBinding heuristicallyResolve(ICPPUnknownBinding binding) {
 		IBinding[] resolved = HeuristicResolver.resolveUnknownBinding(binding);
-		return resolved.length == 1 && resolved[0] instanceof IEnumeration;
-	}
-	
-	private static boolean heuristicallyResolvesToEnumerator(ICPPUnknownBinding binding) {
-		IBinding[] resolved = HeuristicResolver.resolveUnknownBinding(binding);
-		return resolved.length == 1 && resolved[0] instanceof IEnumerator;
+		if (resolved.length == 1) {
+			return resolved[0];
+		}
+		return binding;
 	}
 	
 	// Note on the get___PreferenceKey() functions below:
@@ -2024,6 +2080,7 @@
 		highlightings.put(new Key(230), new EnumeratorHighlighting());
 		highlightings.put(new Key(240), new ContextSensitiveKeywordHighlighting());
 		highlightings.put(new Key(250), new VariablePassedByNonconstRefHighlighting());
+		highlightings.put(new Key(260), new EnumClassHighlighting());
 	}
 
 	private static final String ExtensionPoint = "semanticHighlighting"; //$NON-NLS-1$
diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt
index 19a3b68..f2ae62d 100644
--- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt
+++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/ColorSettingPreviewCode.txt
@@ -21,6 +21,7 @@
 class MyClass {
 public:
   enum Number { ZERO, ONE, TWO };
+  enum class NumberClass { ZERO, ONE, TWO };
   static char staticField;
   int field;
   virtual Number vmethod() const;