package org.rubypeople.rdt.internal.codeassist; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtensionRegistry; import org.eclipse.core.runtime.PerformanceStats; import org.eclipse.core.runtime.Platform; import org.rubypeople.rdt.core.IRubyElement; import org.rubypeople.rdt.core.IRubyScript; import org.rubypeople.rdt.core.RubyCore; import org.rubypeople.rdt.core.RubyModelException; import org.rubypeople.rdt.core.codeassist.CodeResolver; import org.rubypeople.rdt.core.codeassist.ResolveContext; public class SelectionEngine { private static final String PERFORMANCE_EVENT = "org.rubypeople.rdt.core/perf/selection_engine"; private static final boolean MEASURE_PERFORMANCE = PerformanceStats.isEnabled(PERFORMANCE_EVENT); private static final String EXTENSION_POINT = "codeResolver"; private ArrayList<CodeResolver> fResolvers; /** * Combines all the resolved elements from all resolvers. FIXME Need to make it so any resolver can modify the * existing list (add or remove)! * * @param script * @param start * @param end * @return * @throws RubyModelException */ public IRubyElement[] select(IRubyScript script, int start, int end) throws RubyModelException { ResolveContext context = new ResolveContext(script, start, end); List<CodeResolver> resolvers = getResolvers(); for (CodeResolver resolver : resolvers) { PerformanceStats stats = null; if (MEASURE_PERFORMANCE) { stats = PerformanceStats.getStats(PERFORMANCE_EVENT, resolver); stats.startRun(resolver.getClass().getName()); } resolver.select(context); if (MEASURE_PERFORMANCE) { stats.endRun(); } } if (MEASURE_PERFORMANCE) { PerformanceStats.printStats(); } return context.getResolved(); } private List<CodeResolver> getResolvers() { if (fResolvers == null) { fResolvers = new ArrayList<CodeResolver>(); IExtensionRegistry registry = Platform.getExtensionRegistry(); List<IConfigurationElement> elements = new ArrayList<IConfigurationElement>(Arrays.asList(registry .getConfigurationElementsFor(RubyCore.PLUGIN_ID, EXTENSION_POINT))); sortParticipants(elements); for (IConfigurationElement configurationElement : elements) { try { CodeResolver resolver = (CodeResolver) configurationElement.createExecutableExtension("class"); fResolvers.add(resolver); } catch (CoreException e) { RubyCore.log(e); } } } return fResolvers; } private void sortParticipants(List<IConfigurationElement> group) { Collections.sort(group, new Comparator<IConfigurationElement>() { public int compare(IConfigurationElement a, IConfigurationElement b) { if (a == b) return 0; String id = a.getAttribute("id"); //$NON-NLS-1$ if (id == null) return -1; IConfigurationElement[] requiredElements = b.getChildren("requires"); //$NON-NLS-1$ for (int i = 0, length = requiredElements.length; i < length; i++) { IConfigurationElement required = requiredElements[i]; if (id.equals(required.getAttribute("id"))) //$NON-NLS-1$ return 1; } return -1; } }); } }