summaryrefslogtreecommitdiffstats
path: root/rba.tool.editor.ui/src/rba/tool/editor/ui/contentassist/RBAModelExpressionScopeCreator.xtend
blob: 16d812253983bf7803a6881c4ef14816cfc2342d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
	}
}