1 | /* |
---|
2 | * generated by Xtext |
---|
3 | */ |
---|
4 | package com.framsticks.framclipse.scoping; |
---|
5 | |
---|
6 | import static com.framsticks.framclipse.framScript.FramScriptPackage.Literals.ARRAY_ELEMENT_EXPRESSION__ARRAY; |
---|
7 | import static com.framsticks.framclipse.framScript.FramScriptPackage.Literals.QUALIFIED_EXPRESSION__CHILD; |
---|
8 | import static com.framsticks.framclipse.framScript.FramScriptPackage.Literals.QUALIFIED_EXPRESSION__PARENT; |
---|
9 | |
---|
10 | import java.util.ArrayList; |
---|
11 | import java.util.List; |
---|
12 | import java.util.Map; |
---|
13 | import java.util.Map.Entry; |
---|
14 | |
---|
15 | import org.eclipse.emf.common.util.EList; |
---|
16 | import org.eclipse.emf.common.util.TreeIterator; |
---|
17 | import org.eclipse.emf.common.util.URI; |
---|
18 | import org.eclipse.emf.ecore.EObject; |
---|
19 | import org.eclipse.emf.ecore.EReference; |
---|
20 | import org.eclipse.emf.ecore.EStructuralFeature; |
---|
21 | import org.eclipse.emf.ecore.resource.Resource; |
---|
22 | import org.eclipse.emf.ecore.resource.impl.ResourceImpl; |
---|
23 | import org.eclipse.xtext.resource.EObjectDescription; |
---|
24 | import org.eclipse.xtext.resource.IEObjectDescription; |
---|
25 | import org.eclipse.xtext.scoping.IScope; |
---|
26 | import org.eclipse.xtext.scoping.Scopes; |
---|
27 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; |
---|
28 | import org.eclipse.xtext.scoping.impl.SimpleScope; |
---|
29 | |
---|
30 | import com.framsticks.framclipse.framScript.Block; |
---|
31 | import com.framsticks.framclipse.framScript.Code; |
---|
32 | import com.framsticks.framclipse.framScript.FramScriptFactory; |
---|
33 | import com.framsticks.framclipse.framScript.Function; |
---|
34 | import com.framsticks.framclipse.framScript.GotoStatment; |
---|
35 | import com.framsticks.framclipse.framScript.Invocation; |
---|
36 | import com.framsticks.framclipse.framScript.LabeledStatement; |
---|
37 | import com.framsticks.framclipse.framScript.Model; |
---|
38 | import com.framsticks.framclipse.framScript.ProposableFunctionImpl; |
---|
39 | import com.framsticks.framclipse.framScript.ProposableVariableDeclarationImpl; |
---|
40 | import com.framsticks.framclipse.framScript.QualifiedExpression; |
---|
41 | import com.framsticks.framclipse.framScript.Statement; |
---|
42 | import com.framsticks.framclipse.framScript.VariableDeclaration; |
---|
43 | import com.framsticks.framclipse.framScript.VariableDeclarations; |
---|
44 | import com.framsticks.framclipse.framScript.VariableRef; |
---|
45 | import com.framsticks.framclipse.script.ConstantProvider; |
---|
46 | import com.framsticks.framclipse.script.ExpressionTraverser; |
---|
47 | import com.framsticks.framclipse.script.model.Element; |
---|
48 | import com.framsticks.framclipse.script.model.Type; |
---|
49 | import com.google.common.collect.Lists; |
---|
50 | import com.google.common.collect.Maps; |
---|
51 | import com.google.inject.Inject; |
---|
52 | |
---|
53 | /** |
---|
54 | * This class contains custom scoping description. |
---|
55 | * |
---|
56 | * see : http://www.eclipse.org/Xtext/documentation/latest/xtext.html#scoping |
---|
57 | * on how and when to use it |
---|
58 | * |
---|
59 | */ |
---|
60 | public class FramScriptScopeProvider extends AbstractDeclarativeScopeProvider { |
---|
61 | |
---|
62 | private final ConstantProvider provider; |
---|
63 | |
---|
64 | private final ExpressionTraverser traverser; |
---|
65 | |
---|
66 | private Resource resource; |
---|
67 | |
---|
68 | private Map<String, IScope> typesScopes = Maps.newHashMap(); |
---|
69 | private Map<Type, IScope> functionScopes = Maps.newHashMap(); |
---|
70 | private Map<Type, IScope> fieldScopes = Maps.newHashMap(); |
---|
71 | |
---|
72 | @Inject |
---|
73 | public FramScriptScopeProvider(ConstantProvider provider, ExpressionTraverser traverser) { |
---|
74 | this.provider = provider; |
---|
75 | this.traverser = traverser; |
---|
76 | this.resource = new ResourceImpl(URI.createURI("/")); |
---|
77 | initTypes(); |
---|
78 | } |
---|
79 | |
---|
80 | protected void initTypes() { |
---|
81 | List<Function> allFunctions = Lists.newArrayList(); |
---|
82 | List<VariableDeclaration> allFields = Lists.newArrayList(); |
---|
83 | |
---|
84 | for (Entry<String, Map<String, Type>> entry : provider.getTypes().entrySet()) { |
---|
85 | List<VariableDeclaration> types = Lists.newArrayList(); |
---|
86 | for (Type type : entry.getValue().values()) { |
---|
87 | types.add(createType(type)); |
---|
88 | |
---|
89 | ArrayList<Function> functions = Lists.newArrayList(); |
---|
90 | ArrayList<VariableDeclaration> fields = Lists.newArrayList(); |
---|
91 | for (Element element : type.getElements()) { |
---|
92 | if (element.isFunction()) { |
---|
93 | functions.add(createFunction(element)); |
---|
94 | } else { |
---|
95 | fields.add(createField(element)); |
---|
96 | } |
---|
97 | } |
---|
98 | functionScopes.put(type, Scopes.scopeFor(functions)); |
---|
99 | fieldScopes.put(type, Scopes.scopeFor(fields)); |
---|
100 | allFunctions.addAll(functions); |
---|
101 | allFields.addAll(fields); |
---|
102 | } |
---|
103 | typesScopes.put(entry.getKey(), Scopes.scopeFor(types)); |
---|
104 | } |
---|
105 | |
---|
106 | functionScopes.put(null, Scopes.scopeFor(allFunctions)); |
---|
107 | fieldScopes.put(null, Scopes.scopeFor(allFields)); |
---|
108 | } |
---|
109 | |
---|
110 | protected IScope scope_Invocation_function(Invocation inv, EReference ref) { |
---|
111 | QualifiedExpression parent = getParent(inv); |
---|
112 | IScope scope; |
---|
113 | if (parent != null) { |
---|
114 | scope = scope_Invocation_function(parent, ref); |
---|
115 | } else { |
---|
116 | scope = scope_Invocation_function(getFunction(inv), ref); |
---|
117 | } |
---|
118 | scope = filterByArgumentsCount(scope, inv.getArgs().size()); |
---|
119 | return scope; |
---|
120 | } |
---|
121 | |
---|
122 | protected IScope scope_Invocation_function(QualifiedExpression inv, EReference ref) { |
---|
123 | Type type = traverser.getLastType(inv); |
---|
124 | IScope scope = functionScopes.get(type); |
---|
125 | return scope != null ? scope : IScope.NULLSCOPE; |
---|
126 | } |
---|
127 | |
---|
128 | protected IScope scope_Invocation_function(Function f, EReference ref) { |
---|
129 | IScope scope = delegateGetScope(f, ref); |
---|
130 | scope = addAliases(scope); |
---|
131 | return scope; |
---|
132 | } |
---|
133 | |
---|
134 | private IScope filterByArgumentsCount(IScope scope, int size) { |
---|
135 | List<IEObjectDescription> filtered = Lists.newArrayList(); |
---|
136 | for (IEObjectDescription desc : scope.getAllElements()) { |
---|
137 | Function function = (Function) desc.getEObjectOrProxy(); |
---|
138 | if (function.getParams().size() == size) { |
---|
139 | filtered.add(desc); |
---|
140 | } |
---|
141 | } |
---|
142 | return new SimpleScope(filtered); |
---|
143 | } |
---|
144 | |
---|
145 | private IScope addAliases(IScope scope) { |
---|
146 | Iterable<IEObjectDescription> contents = scope.getAllElements(); |
---|
147 | List<IEObjectDescription> withAliases = Lists.newArrayList(contents); |
---|
148 | for (IEObjectDescription desc : contents) { |
---|
149 | Function function = (Function) desc.getEObjectOrProxy(); |
---|
150 | for (String string : function.getAliases()) { |
---|
151 | withAliases.add(EObjectDescription.create(string, function)); |
---|
152 | } |
---|
153 | } |
---|
154 | return new SimpleScope(withAliases); |
---|
155 | } |
---|
156 | |
---|
157 | protected IScope scope_VariableRef_var(VariableRef var, EReference ref) { |
---|
158 | QualifiedExpression parent = getParent(var); |
---|
159 | if (parent != null) { |
---|
160 | return scope_VariableRef_var(parent, ref); |
---|
161 | } else { |
---|
162 | return scope_VariableRef_var(getBlock(var), ref); |
---|
163 | } |
---|
164 | } |
---|
165 | |
---|
166 | protected IScope scope_VariableRef_var(QualifiedExpression var, EReference ref) { |
---|
167 | Type type = traverser.getLastType(var); |
---|
168 | IScope scope = fieldScopes.get(type); |
---|
169 | return scope != null ? scope : IScope.NULLSCOPE; |
---|
170 | } |
---|
171 | |
---|
172 | protected IScope scope_VariableRef_var(Block block, EReference ref) { |
---|
173 | List<VariableDeclaration> vars = Lists.newArrayList(); |
---|
174 | for (Statement stmt : block.getStatements()) { |
---|
175 | if (stmt instanceof VariableDeclarations) { |
---|
176 | vars.addAll(((VariableDeclarations) stmt).getVars()); |
---|
177 | } |
---|
178 | } |
---|
179 | return Scopes.scopeFor(vars, getScope(block.eContainer(), ref)); |
---|
180 | } |
---|
181 | |
---|
182 | protected IScope scope_VariableRef_var(Function f, EReference ref) { |
---|
183 | List<VariableDeclaration> vars = Lists.newArrayList(); |
---|
184 | vars.addAll(f.getParams()); |
---|
185 | return Scopes.scopeFor(vars, getScope(f.eContainer(), ref)); |
---|
186 | } |
---|
187 | |
---|
188 | protected IScope scope_VariableRef_var(Code code, EReference ref) { |
---|
189 | List<VariableDeclaration> vars = Lists.newArrayList(); |
---|
190 | for (VariableDeclarations declarations : code.getGlobals()) { |
---|
191 | vars.addAll(declarations.getVars()); |
---|
192 | } |
---|
193 | return Scopes.scopeFor(vars, getScope(code.eContainer(), ref)); |
---|
194 | } |
---|
195 | |
---|
196 | protected IScope scope_VariableRef_var(Model model, EReference ref) { |
---|
197 | // IScope outerScope = delegateGetScope(model, ref).getOuterScope(); |
---|
198 | IScope types = typesScopes.get(getExtension(model)); |
---|
199 | return new SimpleScope(types.getAllElements()); |
---|
200 | } |
---|
201 | |
---|
202 | protected IScope scope_GotoStatment_dest(GotoStatment stmt, EReference ref) { |
---|
203 | Block code = getFunction(stmt).getCode(); |
---|
204 | List<LabeledStatement> labels = Lists.newArrayList(); |
---|
205 | for (TreeIterator<EObject> i = code.eAllContents(); i.hasNext();) { |
---|
206 | EObject object = i.next(); |
---|
207 | if (object instanceof LabeledStatement) { |
---|
208 | labels.add((LabeledStatement) object); |
---|
209 | } |
---|
210 | } |
---|
211 | return Scopes.scopeFor(labels); |
---|
212 | } |
---|
213 | |
---|
214 | private Function createFunction(Element element) { |
---|
215 | Function function = new ProposableFunctionImpl(element); |
---|
216 | EList<VariableDeclaration> params = function.getParams(); |
---|
217 | for (int i = 0; i < element.getArguments().size(); i++) { |
---|
218 | params.add(createVariableDeclaration(element.getArguments().get(i).getName(i))); |
---|
219 | } |
---|
220 | resource.getContents().add(function); |
---|
221 | return function; |
---|
222 | } |
---|
223 | |
---|
224 | private VariableDeclaration createField(Element element) { |
---|
225 | VariableDeclaration field = new ProposableVariableDeclarationImpl(element); |
---|
226 | resource.getContents().add(field); |
---|
227 | return field; |
---|
228 | } |
---|
229 | |
---|
230 | private VariableDeclaration createType(Type type) { |
---|
231 | VariableDeclaration global = new ProposableVariableDeclarationImpl(type); |
---|
232 | resource.getContents().add(global); |
---|
233 | return global; |
---|
234 | } |
---|
235 | |
---|
236 | private VariableDeclaration createVariableDeclaration(String name) { |
---|
237 | VariableDeclaration var = FramScriptFactory.eINSTANCE.createVariableDeclaration(); |
---|
238 | var.setName(name); |
---|
239 | resource.getContents().add(var); |
---|
240 | return var; |
---|
241 | } |
---|
242 | |
---|
243 | private QualifiedExpression getParent(QualifiedExpression expr) { |
---|
244 | EStructuralFeature feature = expr.eContainingFeature(); |
---|
245 | if (feature.equals(QUALIFIED_EXPRESSION__CHILD)) { |
---|
246 | return (QualifiedExpression) expr.eContainer(); |
---|
247 | } else if (feature.equals(QUALIFIED_EXPRESSION__PARENT) |
---|
248 | || feature.equals(ARRAY_ELEMENT_EXPRESSION__ARRAY)) { |
---|
249 | return getParent((QualifiedExpression) expr.eContainer()); |
---|
250 | } else { |
---|
251 | return null; |
---|
252 | } |
---|
253 | } |
---|
254 | |
---|
255 | private Block getBlock(EObject object) { |
---|
256 | while (object != null && !(object instanceof Block)) { |
---|
257 | object = object.eContainer(); |
---|
258 | } |
---|
259 | return (Block) object; |
---|
260 | } |
---|
261 | |
---|
262 | private Function getFunction(EObject object) { |
---|
263 | while (object != null && !(object instanceof Function)) { |
---|
264 | object = object.eContainer(); |
---|
265 | } |
---|
266 | return (Function) object; |
---|
267 | } |
---|
268 | |
---|
269 | private String getExtension(EObject object) { |
---|
270 | return object.eResource().getURI().fileExtension(); |
---|
271 | } |
---|
272 | |
---|
273 | } |
---|