summaryrefslogtreecommitdiffstats
path: root/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist
diff options
context:
space:
mode:
authorKenji Hosokawa <khosokawa@jp.adit-jv.com>2021-08-03 18:42:39 +0900
committerKenji Hosokawa <khosokawa@jp.adit-jv.com>2021-08-06 19:32:38 +0900
commitbe4f78978faba3d3ceb88df02a7f93a2e09ff1e0 (patch)
tree1f3f1a96251ac4f655c8a96fc33d5d4ee779cd06 /rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist
parent71ca7c6cab863767ef30c8bd05b2bbfda8731cb5 (diff)
Initial commit
Bug-AGL: SPEC-4033 Signed-off-by: Kenji Hosokawa <khosokawa@jp.adit-jv.com>
Diffstat (limited to 'rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist')
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelExpressionScopeCreator.xtend74
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelLastSegmentFinder.xtend31
-rw-r--r--rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelProposalProvider.xtend250
3 files changed, 355 insertions, 0 deletions
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelExpressionScopeCreator.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelExpressionScopeCreator.xtend
new file mode 100644
index 0000000..16d8122
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelExpressionScopeCreator.xtend
@@ -0,0 +1,74 @@
+package rba.tool.editor.ui.contentassist
+
+import com.google.inject.Inject
+import java.util.List
+import org.apache.commons.lang.StringUtils
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.xtext.EcoreUtil2
+import org.eclipse.xtext.Keyword
+import org.eclipse.xtext.nodemodel.INode
+import org.eclipse.xtext.nodemodel.util.NodeModelUtils
+import org.eclipse.xtext.scoping.IScope
+import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext
+import rba.core.Constraint
+import rba.core.ObjectReference
+import rba.core.Operator
+import rba.core.PreviousModifier
+import rba.tool.editor.rbaEditorModel.MemberFeatureReference
+import rba.tool.editor.scoping.IExpressionScope
+
+class RBAModelExpressionScopeCreator {
+
+ @Inject(optional=true) IExpressionScope expressionScope;
+
+ def public IScope getExpressionScope(EObject model, ContentAssistContext contentAssistContext) {
+ if (contentAssistContext.lastCompleteNode !== null) {
+ val EObject grammarElement = contentAssistContext.lastCompleteNode.grammarElement;
+ if (grammarElement instanceof Keyword && ".".equals((grammarElement as Keyword).value)) {
+ val INode lastCompleteNodeParent = contentAssistContext.lastCompleteNode.parent;
+ val semanticObject = NodeModelUtils.findActualSemanticObjectFor(lastCompleteNodeParent);
+ val boolean inner = isInnerPrefix(lastCompleteNodeParent.text, contentAssistContext.offset, lastCompleteNodeParent.endOffset);
+ val EObject eObject = getTargetObject(semanticObject, inner);
+ return expressionScope.getFeatureScope(eObject, getOwnerAnchorType(model));
+ }
+ }
+ return null;
+ }
+
+ def private EObject getTargetObject(EObject eObject, boolean inner) {
+ if (eObject instanceof Operator) {
+ return eObject;
+ }
+
+ var ObjectReference objectReference;
+ if (eObject instanceof MemberFeatureReference) {
+ val MemberFeatureReference reference = eObject as MemberFeatureReference;
+ objectReference = ( if (reference.refObject === null) reference.operand.get(0) else reference) as ObjectReference;
+ } else if (eObject instanceof ObjectReference) {
+ objectReference = eObject;
+ } else if (eObject instanceof PreviousModifier) {
+ val List<ObjectReference> objectReferences = EcoreUtil2.getAllContentsOfType(eObject, ObjectReference);
+ objectReference = if (objectReferences.size > 0) objectReferences.last else null;
+ }
+
+ if (inner && objectReference instanceof MemberFeatureReference) {
+ val operand0 = (objectReference as MemberFeatureReference).operand.get(0);
+ objectReference = if(operand0 instanceof ObjectReference) operand0 as ObjectReference else null;
+ }
+ return if (objectReference !== null) objectReference.refObject else null;
+ }
+
+ def private boolean isInnerPrefix(String text, int offset, int endOffset) {
+ val boolean isInnerOffset = offset <= endOffset;
+ val boolean isInnerPrefix = !StringUtils.endsWith(text, ".");
+ return (isInnerOffset && isInnerPrefix);
+ }
+
+ def private IExpressionScope.Anchor getOwnerAnchorType(EObject model) {
+ var EObject owner = EcoreUtil2.getContainerOfType(model, Constraint);
+ if (owner !== null) {
+ return IExpressionScope.Anchor.CONSTRAINT;
+ }
+ return IExpressionScope.Anchor.UNKNOWN;
+ }
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelLastSegmentFinder.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelLastSegmentFinder.xtend
new file mode 100644
index 0000000..e844018
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelLastSegmentFinder.xtend
@@ -0,0 +1,31 @@
+package rba.tool.editor.ui.contentassist
+
+import org.eclipse.xtext.ui.editor.contentassist.FQNPrefixMatcher.LastSegmentFinder
+
+class RBAModelLastSegmentFinder implements LastSegmentFinder {
+
+ override String getLastSegment(String fqn, char delimiter) {
+ if(fqn === null || fqn.length() == 0) {
+ return null;
+ }
+
+ var lookForUppercase = false;
+ var lastDelimiterIndex = -1;
+ for (var int i = 0; i < fqn.length(); i.operator_plusPlus()) {
+ if(lookForUppercase) {
+ if(Character.isUpperCase(fqn.charAt(i))) {
+ return fqn.substring(i);
+ }
+ }
+ lookForUppercase = delimiter == fqn.charAt(i);
+ if(lookForUppercase) {
+ lastDelimiterIndex = i;
+ }
+ }
+ if(lastDelimiterIndex >= 0 && lastDelimiterIndex < fqn.length() - 1) {
+ return fqn.substring(lastDelimiterIndex + 1);
+ }
+ return null;
+ }
+
+}
diff --git a/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelProposalProvider.xtend b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelProposalProvider.xtend
new file mode 100644
index 0000000..c3af655
--- /dev/null
+++ b/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelProposalProvider.xtend
@@ -0,0 +1,250 @@
+/*
+ * generated by Xtext 2.12.0
+ */
+package rba.tool.editor.ui.contentassist
+
+import com.google.common.base.Predicate
+import com.google.common.base.Predicates
+import com.google.inject.Inject
+import org.apache.log4j.Logger
+import org.eclipse.emf.ecore.EObject
+import org.eclipse.emf.ecore.util.EcoreUtil
+import org.eclipse.jface.text.contentassist.ICompletionProposal
+import org.eclipse.jface.viewers.StyledString
+import org.eclipse.swt.graphics.Image
+import org.eclipse.xtext.Assignment
+import org.eclipse.xtext.CrossReference
+import org.eclipse.xtext.Keyword
+import org.eclipse.xtext.RuleCall
+import org.eclipse.xtext.conversion.ValueConverterException
+import org.eclipse.xtext.resource.IEObjectDescription
+import org.eclipse.xtext.scoping.IScope
+import org.eclipse.xtext.ui.editor.contentassist.AbstractJavaBasedContentProposalProvider.DefaultProposalCreator
+import org.eclipse.xtext.ui.editor.contentassist.ConfigurableCompletionProposal
+import org.eclipse.xtext.ui.editor.contentassist.ContentAssistContext
+import org.eclipse.xtext.ui.editor.contentassist.ICompletionProposalAcceptor
+import rba.core.Content
+import rba.core.LambdaExpression
+import rba.core.RBACorePackage
+import rba.core.Variable
+import rba.sound.SoundContent
+import rba.sound.SoundContentSet
+import rba.sound.Zone
+import rba.sound.ZoneSet
+import rba.tool.editor.resource.RBAModelEObjectDescription
+import rba.tool.editor.ui.util.CharacterUtil
+import rba.view.Area
+import rba.view.AreaSet
+import rba.view.Display
+import rba.view.Size
+import rba.view.ViewContent
+import rba.view.ViewContentSet
+
+/**
+ * See https://www.eclipse.org/Xtext/documentation/304_ide_concepts.html#content-assist
+ * on how to customize the content assistant.
+ */
+class RBAModelProposalProvider extends AbstractRBAModelProposalProvider {
+
+ private final static Logger log = Logger.getLogger(RBAModelProposalProvider);
+
+ @Inject RBAModelExpressionScopeCreator expressionScopeCreator;
+
+ override completeKeyword(Keyword keyword, ContentAssistContext contentAssistContext, ICompletionProposalAcceptor acceptor) {
+ if (!CharacterUtil.isKeywordWorthyToPropose(keyword)) {
+ super.completeKeyword(keyword, contentAssistContext, acceptor)
+ }
+ }
+
+ override lookupCrossReference(CrossReference crossReference, ContentAssistContext contentAssistContext, ICompletionProposalAcceptor acceptor) {
+ lookupCrossReference(crossReference, contentAssistContext, acceptor, getFeatureDescriptionPredicate(crossReference, contentAssistContext));
+ }
+
+ def protected Predicate<IEObjectDescription> getFeatureDescriptionPredicate(CrossReference crossReference, ContentAssistContext contentAssistContext) {
+ return Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ if (input.EObjectOrProxy instanceof Variable) {
+ return contentAssistContext.currentModel.internalLambdaExpression(input.EObjectOrProxy);
+ }
+
+ if (input.EObjectOrProxy instanceof Size) {
+ return isValidSizeModel(input.EObjectOrProxy, crossReference)
+ }
+
+ return true;
+ }
+ });
+ }
+
+ def private boolean isValidSizeModel(EObject objectOrProxy, CrossReference crossReference) {
+ var EObject tmpObj
+ if (objectOrProxy.eIsProxy) {
+ // resolve proxy object with crossReference
+ tmpObj = EcoreUtil.resolve(objectOrProxy, crossReference);
+ } else {
+ tmpObj = objectOrProxy
+ }
+ // get the container of the real object
+ if (tmpObj instanceof Size) {
+ if (!(tmpObj.eContainer instanceof Area) && !(tmpObj.eContainer instanceof Content) && !(tmpObj.eContainer instanceof Display)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ def protected boolean internalLambdaExpression(EObject eObj1, EObject eObj2) {
+ if (eObj1 === null || !(eObj2 instanceof Variable)) {
+ return false;
+ }
+
+ if (eObj1 instanceof LambdaExpression && (eObj1 as LambdaExpression).x === eObj2) {
+ return true;
+ }
+
+ return internalLambdaExpression(eObj1.eContainer, eObj2);
+ }
+
+ override protected getProposalFactory(String ruleName, ContentAssistContext contentAssistContext) {
+ return new DefaultProposalCreator(contentAssistContext, ruleName, getQualifiedNameConverter()) {
+ override apply(IEObjectDescription candidate) {
+ if (candidate === null)
+ return null;
+ var ICompletionProposal result = null;
+ var String proposal = qualifiedNameConverter.toString(candidate.getName());
+ if (valueConverter !== null) {
+ try {
+ proposal = valueConverter.toString(proposal);
+ } catch (ValueConverterException e) {
+ log.debug(e.getMessage(), e);
+ return null;
+ }
+ } else if (ruleName !== null) {
+ try {
+ proposal = getValueConverter().toString(proposal, ruleName);
+ } catch (ValueConverterException e) {
+ log.debug(e.getMessage(), e);
+ return null;
+ }
+ }
+ val EObject objectOrProxy = candidate.getEObjectOrProxy();
+ val StyledString displayString = getStyledDisplayString(candidate);
+ val Image image = getImage(candidate);
+ result = createCompletionProposal(proposal, displayString, image, contentAssistContext);
+ if (result instanceof ConfigurableCompletionProposal) {
+ (result as ConfigurableCompletionProposal).setProposalContextResource(contentAssistContext.getResource());
+ (result as ConfigurableCompletionProposal).setAdditionalProposalInfo(objectOrProxy);
+ (result as ConfigurableCompletionProposal).setHover(hover);
+
+ if (candidate instanceof RBAModelEObjectDescription) {
+ (result as ConfigurableCompletionProposal).setCursorPosition((result as ConfigurableCompletionProposal).cursorPosition +
+ (candidate as RBAModelEObjectDescription).getAdditionalInfo().get(0));
+ (result as ConfigurableCompletionProposal).setPriority((result as ConfigurableCompletionProposal).priority +
+ (candidate as RBAModelEObjectDescription).getAdditionalInfo().get(1));
+ }
+ }
+ getPriorityHelper().adjustCrossReferencePriority(result, contentAssistContext.getPrefix());
+ return result;
+ }
+ };
+ }
+
+ override completeAreaSet_Target(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Area || input.EObjectOrProxy instanceof AreaSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeViewContentSet_Target(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof ViewContent || input.EObjectOrProxy instanceof ViewContentSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeViewContentSet_Allocatable(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Area || input.EObjectOrProxy instanceof AreaSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeZoneSet_Target(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Zone || input.EObjectOrProxy instanceof ZoneSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeSoundContentSet_Target(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof SoundContent || input.EObjectOrProxy instanceof SoundContentSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeSoundContentSet_Allocatable(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Zone || input.EObjectOrProxy instanceof ZoneSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeViewContent_Allocatable(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Area || input.EObjectOrProxy instanceof AreaSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeSoundContent_Allocatable(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val Predicate<IEObjectDescription> filter = Predicates.and(new Predicate<IEObjectDescription>() {
+ override public boolean apply(IEObjectDescription input) {
+ return (input.EObjectOrProxy instanceof Zone || input.EObjectOrProxy instanceof ZoneSet);
+ }
+ });
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor, filter);
+ }
+
+ override completeCMemberFeatureReference_RefObject(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ createMemberAndOperatorProposals(model, assignment, context, acceptor);
+ }
+
+ override completeVMemberFeatureReference_RefObject(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ createMemberAndOperatorProposals(model, assignment, context, acceptor);
+ }
+
+ def protected void createMemberAndOperatorProposals(EObject model, Assignment assignment, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val IScope scope = expressionScopeCreator.getExpressionScope(model, context);
+ if (scope === null) {
+ lookupCrossReference((assignment.getTerminal() as CrossReference), context, acceptor);
+ } else {
+ getCrossReferenceProposalCreator().lookupCrossReference(scope, model, RBACorePackage.Literals.OBJECT_REFERENCE__REF_OBJECT, acceptor,
+ getFeatureDescriptionPredicate((assignment.getTerminal() as CrossReference), context), getProposalFactory("ValidID", context));
+ }
+ }
+
+ override complete_OpGetProperty(EObject model, RuleCall ruleCall, ContentAssistContext context, ICompletionProposalAcceptor acceptor) {
+ val IScope scope = expressionScopeCreator.getExpressionScope(model, context);
+ if (scope !== null) {
+ getCrossReferenceProposalCreator().lookupCrossReference(scope, model, RBACorePackage.Literals.OPERATOR__OPERAND, acceptor, Predicates.<IEObjectDescription>alwaysTrue(),
+ getProposalFactory(null, context));
+ }
+ }
+
+}