Skip to main content
summaryrefslogtreecommitdiffstats
blob: 37416636e1dc3483d115cd25946f4ac6da8393e9 (plain) (blame)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package org.eclipse.fx.xtext.statemachine.fx.contentassist;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.fx.ui.controls.styledtext.StyledString;
import org.eclipse.jface.text.contentassist.CompletetionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.xtext.AbstractElement;
import org.eclipse.xtext.Assignment;
import org.eclipse.xtext.CrossReference;
import org.eclipse.xtext.GrammarUtil;
import org.eclipse.xtext.Keyword;
import org.eclipse.xtext.RuleCall;
import org.eclipse.xtext.TerminalRule;
import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext;
import org.eclipse.xtext.ide.editor.contentassist.antlr.ContentAssistContextFactory;
import org.eclipse.xtext.resource.IEObjectDescription;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.IScopeProvider;
import org.eclipse.xtext.util.TextRegion;
import org.eclipse.xtext.xtext.CurrentTypeFinder;

import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;

import javafx.scene.Node;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

@Singleton
public class ContentAssistProvider {
	@Inject
	Provider<ContentAssistContextFactory> contextFactoryProvider;
	@Inject
	Provider<XtextResourceSet> resourceSetProvider;
	@Inject
	ExecutorService pool;
	@Inject
	IScopeProvider scopeProvider;
	@Inject
	CurrentTypeFinder typeFinder;
	
	private Image referenceImage;
	
	public ContentAssistProvider() {
		referenceImage = new Image(getClass().getResource("field_public_obj.png").toExternalForm());
	}

	@SuppressWarnings("restriction")
	public List<ICompletionProposal> doContentAssist(String content, String uri, Integer offset) {
		ContentAssistContextFactory contextFactory = contextFactoryProvider.get();
		XtextResourceSet xtextResourceSet = resourceSetProvider.get();

		XtextResource resource = (XtextResource) xtextResourceSet.getResource(URI.createURI(uri), true);
		contextFactory.setPool(pool);
		ContentAssistContext[] contexts = contextFactory.create(content, new TextRegion(0, 0), offset, resource);

		List<ICompletionProposal> proposal = new ArrayList<>();
		for (int i = 0; i < contexts.length; i++) {
			for (AbstractElement abstractElement : contexts[i].getFirstSetGrammarElements()) {
				createProposals(contexts[i], abstractElement, offset, proposal);
			}
		}

		return proposal;
	}

	private void createProposals(ContentAssistContext context, AbstractElement abstractElement, int offset,
			List<ICompletionProposal> proposal) {
		if (abstractElement instanceof Assignment) {
			Assignment assignment = (Assignment) abstractElement;
			if (assignment.getTerminal() instanceof CrossReference) {
				createProposals(context, assignment.getTerminal(), offset, proposal);
			}
		} else if (abstractElement instanceof RuleCall) {
			RuleCall ruleCall = (RuleCall) abstractElement;
			if (ruleCall.getRule() instanceof TerminalRule && context.getPrefix().isEmpty()) {
				if (ruleCall.getRule().getName().equals("STRING")) {
					// val container = ruleCall.eContainer
					// if (container instanceof Assignment) {
					// proposal = '"' + container.feature + '"'
					// description = ruleCall.rule.name
					// } else {
					// proposal = '"' + ruleCall.rule.name + '"'
					// }
					// editPositions += new
					// ContentAssistResult.EditPosition(context.offset + 1,
					// proposal.length - 2)
				} else {
					EObject container = ruleCall.eContainer();
					if (container instanceof Assignment) {
						proposal.add(new CompletetionProposal(((Assignment) container).getFeature(), offset, 0,
								ruleCall.getRule().getName(), () -> null));
					} else {
						proposal.add(new CompletetionProposal(ruleCall.getRule().getName(), offset, 0,
								ruleCall.getRule().getName(), () -> null));
					}
					// editPositions += new
					// ContentAssistResult.EditPosition(context.offset,
					// proposal.length)
				}
			}
		} else if (abstractElement instanceof Keyword) {
			Keyword w = (Keyword) abstractElement;
			proposal.add(new CompletetionProposal(w.getValue(), offset, 0, w.getValue(), () -> null));
		} else if (abstractElement instanceof CrossReference) {
			CrossReference reference = (CrossReference) abstractElement;
			EClassifier type = typeFinder.findCurrentTypeAfter(reference);
			if (type instanceof EClass) {
				EReference ereference = GrammarUtil.getReference(reference, (EClass) type);
				if (ereference != null) {
					IScope scope = scopeProvider.getScope(context.getCurrentModel(), ereference);
					try {
						for (IEObjectDescription description : scope.getAllElements()) {
							String elementName = description.getName().toString();
							if (elementName.startsWith(context.getPrefix())) {
								StyledString s = new StyledString();
								s.appendSegment(elementName + " - ", "state-default-string");
								s.appendSegment(description.getEClass().getName(), "state-type-info");
								proposal.add(new CompletetionProposal(elementName, offset,
										0, s, () -> new ImageView(referenceImage)));
							}
						}
					} catch (UnsupportedOperationException uoe) {
						// LOG.error('Failed to create content assist proposals
						// for cross-reference.', uoe)
					}
				}
			}
		}
	}

}

Back to the top