/******************************************************************************* * Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH 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 *******************************************************************************/ package de.gebit.integrity.ui.contentassist; import org.eclipse.emf.ecore.EObject; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.xtext.common.types.JvmEnumerationLiteral; import org.eclipse.xtext.common.types.JvmIdentifiableElement; import org.eclipse.xtext.ui.editor.contentassist.ContentProposalPriorities; import com.google.common.base.CharMatcher; /** * A custom proposal priority implementation in order to adjust proposal priorities. * * @author Rene Schneider - initial API and implementation * */ public class DSLContentProposalPriorities extends ContentProposalPriorities { /** * Priority for enumeration literals. */ private static final int ENUM_LITERAL_PRIORITY = 600; /** * Maximum score bonus awarded because of "distance". Distance is measured in dots required to reference the element * in the shortest way - that is, after considering package imports. So if you need to write * "anotherpackage.element" to access an element, it has a distance of one, while "element" would have a distance of * zero and "outerpackage.anotherpackage.element" would be two. */ private static final int CROSS_REFERENCE_DISTANCE_BONUS_MAX = 10; /** * Bonus awarded to the distance score if the element is in the local suite. */ private static final int CROSS_REFERENCE_IN_LOCAL_SUITE_BONUS = 50; /** * Bonus awarded to the distance score if the element is in the local package. */ private static final int CROSS_REFERENCE_IN_LOCAL_PACKAGE_BONUS = 25; @Override protected void adjustPriority(ICompletionProposal aProposal, String aPrefix, int aPriority) { super.adjustPriority(aProposal, aPrefix, aPriority); if (aProposal instanceof IntegrityConfigurableCompletionProposal) { IntegrityConfigurableCompletionProposal tempProposal = (IntegrityConfigurableCompletionProposal) aProposal; EObject tempAdditionalInfo = tempProposal.getAdditionalProposalInfoObject(); // issue #84: enum literals should be prioritized if (tempAdditionalInfo instanceof JvmEnumerationLiteral) { tempProposal.setPriority(ENUM_LITERAL_PRIORITY); } // Only do the following if we have an element of our DSL model. Don't know any other way to find this out // other than checking whether we NOT have a JVM element reference. if (!(tempAdditionalInfo instanceof JvmIdentifiableElement)) { // Prioritize primarily by "distance" to the local position. This is done by calculating a distance // score (higher is better) and adding it to the priority. int tempCrossReferenceDistance = CharMatcher.is('.').countIn(tempProposal.getReplacementString()); int tempCrossReferenceDistanceScore = CROSS_REFERENCE_DISTANCE_BONUS_MAX - tempCrossReferenceDistance; if (tempCrossReferenceDistanceScore < 0) { tempCrossReferenceDistanceScore = 0; } if (tempProposal.isReferencingObjectInLocalPackage()) { if (tempProposal.isReferencingObjectInLocalSuite()) { tempCrossReferenceDistanceScore += CROSS_REFERENCE_IN_LOCAL_SUITE_BONUS; } else { tempCrossReferenceDistanceScore += CROSS_REFERENCE_IN_LOCAL_PACKAGE_BONUS; } } tempProposal.setPriority(tempProposal.getPriority() + tempCrossReferenceDistanceScore); } } } }