Bug 57137 - investigate content type registry performance (merged validation/description when only one content type is eligible)
diff --git a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentType.java b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentType.java
index 2ace8d2..a7f5e1b 100644
--- a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentType.java
+++ b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentType.java
@@ -445,7 +445,9 @@
 		if (tmpDescriber == null)
 			return defaultDescription;
 		ContentDescription description = new ContentDescription(options, this);
-		describe(tmpDescriber, buffer, description);
+		if (describe(tmpDescriber, buffer, description) == IContentDescriber.INVALID)
+			// the contents were actually invalid for the content type
+			return null;
 		// the describer didn't add any details, return default description
 		if (!description.isSet())
 			return defaultDescription;
diff --git a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentTypeCatalog.java b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentTypeCatalog.java
index 1767288..7298856 100644
--- a/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentTypeCatalog.java
+++ b/bundles/org.eclipse.core.runtime/src/org/eclipse/core/internal/content/ContentTypeCatalog.java
@@ -251,7 +251,7 @@
 
 	IContentType[] findContentTypesFor(ContentTypeMatcher matcher, InputStream contents, String fileName) throws IOException {
 		final ILazySource buffer = ContentTypeManager.readBuffer(contents);
-		IContentType[] selected = internalFindContentTypesFor(matcher, buffer, fileName);
+		IContentType[] selected = internalFindContentTypesFor(matcher, buffer, fileName, true);
 		// give the policy a chance to change the results
 		ISelectionPolicy policy = matcher.getPolicy();
 		if (policy != null)
@@ -299,7 +299,7 @@
 	}
 
 	private IContentDescription getDescriptionFor(ContentTypeMatcher matcher, ILazySource contents, String fileName, QualifiedName[] options) throws IOException {
-		IContentType[] selected = internalFindContentTypesFor(matcher, contents, fileName);
+		IContentType[] selected = internalFindContentTypesFor(matcher, contents, fileName, false);
 		if (selected.length == 0)
 			return null;
 		// give the policy a chance to change the results
@@ -369,7 +369,7 @@
 		return result;
 	}
 
-	private IContentType[] internalFindContentTypesFor(ContentTypeMatcher matcher, ILazySource buffer, String fileName) throws IOException {
+	private IContentType[] internalFindContentTypesFor(ContentTypeMatcher matcher, ILazySource buffer, String fileName, boolean forceValidation) throws IOException {
 		final IContentType[][] subset;
 		final Comparator validPolicy;
 		Comparator indeterminatePolicy;
@@ -383,6 +383,13 @@
 			indeterminatePolicy = policyGeneralIsBetter;
 			validPolicy = policySpecificIsBetter;
 		}
+		int total = subset[0].length + subset[1].length;
+		if (total == 0)
+			// don't do further work if subset is empty
+			return subset[0];
+		if (!forceValidation && total == 1)
+			// do not do validation if not forced and only one was found (caller will validate later)
+			return subset[0].length == 1 ? subset[0] : subset[1];
 		return internalFindContentTypesFor(buffer, subset, validPolicy, indeterminatePolicy);
 	}
 
@@ -450,9 +457,9 @@
 			Set initialSet = (Set) associations.get(FileSpec.getMappingKeyFor(text));
 			if (initialSet != null && !initialSet.isEmpty()) {
 				// copy so we can modify
-				result = new  HashSet(initialSet);
+				result = new HashSet(initialSet);
 				// invert the last two bits so it is easier to compare
-				typeMask ^= (IContentType.IGNORE_PRE_DEFINED | IContentType.IGNORE_USER_DEFINED);				
+				typeMask ^= (IContentType.IGNORE_PRE_DEFINED | IContentType.IGNORE_USER_DEFINED);
 				for (Iterator i = result.iterator(); i.hasNext();) {
 					ContentType contentType = (ContentType) i.next();
 					if (!contentType.hasFileSpec(text, typeMask, true))